2009-07-15 27 views
19

मेरे पास कुछ ऐसे स्थान हैं जहां कुछ प्रकार के कैश को लागू करना उपयोगी हो सकता है। उदाहरण के लिए कस्टम स्ट्रिंग्स के आधार पर संसाधन लुकअप करने के मामलों में, प्रतिबिंब का उपयोग करके गुणों के नाम ढूंढना, या प्रति संपत्ति नाम केवल PropertyChangedEventArgs रखना है।सी #: स्मार्ट कैश को कैसे कार्यान्वित करें

पिछले एक के एक साधारण उदाहरण:

public static class Cache 
{ 
    private static Dictionary<string, PropertyChangedEventArgs> cache; 
    static Cache() 
    { 
     cache = new Dictionary<string, PropertyChangedEventArgs>(); 
    } 
    public static PropertyChangedEventArgs GetPropertyChangedEventArgs(
     string propertyName) 
    { 
     if (cache.ContainsKey(propertyName)) 
      return cache[propertyName]; 

     return cache[propertyName] = new PropertyChangedEventArgs(propertyName); 
    } 
} 

लेकिन, यह काम होगा अच्छी तरह से? उदाहरण के लिए यदि हमारे पास अलग-अलग संपत्ति नामों का पूरा भार था, तो इसका मतलब यह होगा कि हम एक विशाल कैश के साथ खत्म हो जाएंगे, वहां कभी भी कचरा इकट्ठा या कुछ भी नहीं होगा। मैं कल्पना कर रहा हूं कि कैश किया गया क्या बड़ा मूल्य है और यदि एप्लिकेशन एक लंबे समय से चल रहा है, तो यह किसी प्रकार की समस्या के रूप में समाप्त हो सकता है ... या आप क्या सोचते हैं? एक अच्छा कैश कैसे लागू किया जाना चाहिए? क्या यह ज्यादातर उद्देश्यों के लिए पर्याप्त है? कुछ अच्छे कैश कार्यान्वयन के किसी भी उदाहरण जो समझने में बहुत मुश्किल नहीं हैं या लागू करने के लिए बहुत जटिल हैं?

+12

"* वहाँ कंप्यूटर विज्ञान में केवल दो हार्ड चीजें हैं:। कैश अमान्यकरण और नामकरण बातें *" - फिल Karlton – JulianR

+1

यह नहीं एक पूरी जवाब लायक, लेकिन इस विशेष कार्यान्वयन होगा है एक बहु थ्रेडेड वातावरण में शानदार रूप से विफल। कम से कम आपको 'GetPropertyChangedEventArgs() 'में' कैश 'तक पहुंच के चारों ओर एक लॉक की आवश्यकता है। बस किसी भी व्यक्ति की मदद करने की कोशिश कर रहा है जो इस के साथ आता है और प्रतिलिपि बनाता है। – aaronburro

उत्तर

18

आप अपने प्रत्येक कैश किए गए आइटम को WeakReference में लपेट सकते हैं। यह जीसी को वस्तुओं को पुनः प्राप्त करने की इजाजत देता है, और जब आवश्यक हो, हालांकि यह आपको कैश से आइटम गायब होने पर कोई दानेदार नियंत्रण नहीं देता है, या आपको स्पष्ट समाप्ति नीतियों आदि को लागू करने की अनुमति देता है।

(Ha मैंने अभी देखा है कि MSDN page पर दिया गया उदाहरण एक साधारण कैशिंग कक्षा है।)

+1

के प्रकार का निर्धारण करने दें ठंडा! इस मामले में वीक रेफरेंस वास्तव में क्या करता है? – Svish

+1

इस पृष्ठ में एक अच्छा स्पष्टीकरण है: http://msdn.microsoft.com/en-us/library/ms404247.aspx – LukeH

+4

प्रैक्टिस में, मुझे लगता है कि .NET जीसी इतना कुशल/आक्रामक है कि कमजोर संदर्भ लटका नहीं है लंबे समय तक, जिसका अर्थ है कि वे केवल उन डेटा के लिए उपयुक्त हैं जो अल्पकालिक और/या फिर से बनाने के लिए सस्ती हैं। – LukeH

3

यह है करने के लिए एक अच्छा बहस है, लेकिन अपने आवेदन के आधार है, यहां कुछ युक्तियां है:

आप कैश का अधिकतम आकार, क्या पुराने आइटम के साथ क्या करना है, तो अपने कैश भरा हुआ है परिभाषित करना चाहिए, एक सफाई है रणनीति, कैश में ऑब्जेक्ट के रहने का समय निर्धारित करें, क्या आपके कैश को कहीं और जारी रखा जाना चाहिए, स्मृति असामान्य समाप्ति के मामले में, ...

+1

एक scavenging रणनीति क्या है? – Svish

+4

स्कैवेंगिंग एल्गोरिदम कैश से आइटम्स को मुक्त कैश स्टोरेज संसाधनों में हटाने का उत्तरदायी है। –

+0

आह, ठीक है। यह समझ आता है। – Svish

24

यह एक बड़ी समस्या है, आपको इसकी आवश्यकता है समस्या का डोमेन निर्धारित करें और सही तकनीक लागू करें। उदाहरण के लिए, आप वस्तुओं की समाप्ति का वर्णन कैसे करेंगे? क्या वे समय के एक निश्चित अंतराल पर बाँध बन जाते हैं? क्या वे बाहरी घटना से निकल जाते हैं? यह कितनी बार होता है? इसके अतिरिक्त, आपके पास कितनी ऑब्जेक्ट्स हैं? अंत में, वस्तु उत्पन्न करने के लिए कितना खर्च होता है?

सबसे सरल रणनीति सीधे ऊपर की तरह, जैसा कि आप ऊपर है, करना होगा। यह मानता है कि ऑब्जेक्ट्स कभी समाप्त नहीं होते हैं, और आपके मेमोरी को और चलाने के लिए इतने सारे नहीं हैं कि आपको लगता है कि इन ऑब्जेक्ट्स को बनाने की लागत शुरू करने के लिए कैश के उपयोग की गारंटी देती है।

अगली परत ऑब्जेक्ट्स की संख्या को सीमित करने के लिए हो सकती है, और एलआरयू (कम से कम हाल ही में उपयोग की जाने वाली) जैसी निहित समाप्ति नीति का उपयोग कर सकती है। ऐसा करने के लिए आप आमतौर पर अपने शब्दकोश के अलावा एक दोगुनी लिंक्ड सूची का उपयोग करेंगे, और जब भी ऑब्जेक्ट्स का उपयोग किया जाता है तो इसे सूची के सामने ले जाया जाता है। फिर, यदि आपको कोई नई वस्तु जोड़ने की आवश्यकता है, लेकिन यह कुल ऑब्जेक्ट्स की आपकी सीमा से अधिक है, तो आप सूची के पीछे से हटा देंगे।

अगला, आपको समय पर या कुछ बाहरी उत्तेजना के आधार पर स्पष्ट समाप्ति को लागू करने की आवश्यकता हो सकती है। इसके लिए आपको किसी प्रकार की समाप्ति घटना की आवश्यकता होगी जिसे बुलाया जा सके।

जैसा कि आप देख सकते हैं कि कैशिंग में बहुत सारे डिज़ाइन हैं, इसलिए आपको अपने डोमेन और इंजीनियर को उचित रूप से समझने की आवश्यकता है। आपने मुझे विनिर्देशों पर चर्चा करने के लिए पर्याप्त जानकारी प्रदान नहीं की, मुझे लगा।

पीएस कृपया अपनी कक्षा को परिभाषित करते समय जेनेरिक का उपयोग करने पर विचार करें ताकि कई प्रकार की वस्तुओं को संग्रहीत किया जा सके, इस प्रकार आपके कैशिंग कोड को पुन: उपयोग किया जा सके।

+2

+1 कई कारकों का उल्लेख करने और बुनियादी समाधान का सुझाव देने के लिए +1। –

+0

मुझे उम्मीद है कि मुझे स्पेसफिक्स छोड़ दिया गया है क्योंकि मुझे उम्मीद थी कि मुझे इसके बारे में क्या सोचना है, इस बारे में अधिक सामान्य सलाह मिलेगी। इसलिए जेनिक्स का उपयोग करने पर, क्या आप कैश के साथ कैश को स्वैप करना और बाहर निकलना चाहते हैं टी के साथ सभी संपत्तिChangedEventArgs भी? या कुछ और चालाक? अन्य सभी ऑब्जेक्ट्स को एक स्ट्रिंग द्वारा पहचानने के लिए समझ में नहीं आता है ... – Svish

+1

बस मूल जेनेरिक हाँ, आप के समान पैटर्न का उपयोग करना चाहेंगे और अपने कैश के उपयोगकर्ता को के और वी –

3

यह एक आम समस्या है जिसमें आपके आवेदन की आवश्यकता के आधार पर कई समाधान हैं। यह इतना आम है कि माइक्रोसॉफ्ट ने इसे संबोधित करने के लिए एक संपूर्ण पुस्तकालय जारी किया। आपको अपना खुद का कैश रोल करने से पहले माइक्रोसॉफ्ट वेग की जांच करनी चाहिए। http://msdn.microsoft.com/en-us/data/cc655792.aspx इस सहायता की आशा करें।

+0

+1 - यह लाइब्रेरी ऐसा लगता है कि इसकी जड़ें एंटरप्राइज़ लाइब्रेरी से कैशिंग एप्लिकेशन ब्लॉक में हैं। –

+0

जिसे अब "ऐपफैब्रिक कैशिंग सेवा" कहा जाता है। यहां दो कीवर्ड गायब हैं: पोर्टेबिलिटी और मुफ़्त। माइक्रोसॉफ्ट बस .NET के मानक हिस्से के रूप में कुछ क्यों नहीं छोड़ सकता है? –

1

आप WeakReference का उपयोग कर सकते हैं, लेकिन यदि आपका ऑब्जेक्ट इतना बड़ा नहीं है क्योंकि WeakReference ऑब्जेक्ट की तुलना में अधिक मेमोरी ले रहा है जो एक अच्छी तकनीक नहीं है। साथ ही, यदि ऑब्जेक्ट एक शॉर्ट-टाइम उपयोग है, जहां यह जीसी पर पीढ़ी 0 से पीढ़ी 1 तक कभी नहीं बनायेगा, तो WeakReference की आवश्यकता नहीं है लेकिन ऑब्जेक्ट पर आईडीस्पोजेबल इंटरफ़ेस SuppressFinalize पर रिलीज़ के साथ होगा।

यदि आप जीवनकाल को नियंत्रित करना चाहते हैं तो आपको अपने कैश में ऑब्जेक्ट पर वांछित एक्स्पिरेशनटाइम को फिर से टाइमटाइम/टाइमपैन अपडेट करने के लिए टाइमर चाहिए।

महत्वपूर्ण बात यह है कि यदि वस्तु बड़ी है तो वीक रेफरेंस का चयन करें और मजबूत संदर्भ का उपयोग करें। साथ ही, आप शब्दकोश पर क्षमता निर्धारित कर सकते हैं और ऑब्जेक्ट को क्रमबद्ध करने और इसे शब्दकोश में कमरे में लोड करते समय अतिरिक्त अस्थायी अनुरोध करने के लिए कतार बना सकते हैं, फिर इसे temp निर्देशिका से साफ़ करें।

9

ऐसा लगता है कि .NET 4.0 अब System.Runtime.Caching को कई प्रकार की चीज़ों को कैशिंग के लिए समर्थन देता है। पहिया को फिर से आविष्कार करने के बजाय, आपको पहले उसमें देखना चाहिए। अधिक विवरण:

http://msdn.microsoft.com/en-us/library/system.runtime.caching%28VS.100%29.aspx

+4

इसके अलावा यह एक कुंजी के रूप में स्ट्रिंग का उपयोग करता है, और मानचित्र के मूल्य के लिए ऑब्जेक्ट का उपयोग करता है! मनुष्य क्या निराशाजनक है, वे कैश की तरह एक सामान्य एपीआई कैसे कार्यान्वित कर सकते हैं और कुंजी/ऑब्जेक्ट प्रकार के लिए जेनरिक का उपयोग नहीं कर सकते? – marq

+0

ठीक है, मैं एक कुंजी के लिए स्ट्रिंग का उपयोग कर समझ सकता हूं। मुझे किसी भी हैश ऑब्जेक्ट्स के बारे में पता नहीं है जो कम से कम स्ट्रिंग-आधारित चीज़ में कुंजी को स्थानांतरित नहीं करते हैं। और ऑब्जेक्ट सिर्फ एक सामान्य कंटेनर नहीं है? –

+0

@BrendanByrd प्रत्येक ऑब्जेक्ट में पहले से ही हैश कोड विधि है। – Casey

संबंधित मुद्दे