2009-05-30 13 views
14

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

ऑब्जेक्ट्स को लंबे समय तक जीवित रहने के लिए मैं किन तरीकों को लागू कर सकता हूं?

उत्तर

3

नहीं, वीक रेफरेंस इसके लिए अच्छा नहीं है क्योंकि कचरा कलेक्टर का व्यवहार समय के साथ बदल सकता है और बदल जाएगा और आपका कैश आज के व्यवहार पर निर्भर नहीं होना चाहिए। आपके नियंत्रण के बाहर भी कई कारक स्मृति दबाव को प्रभावित कर सकते हैं।

.NET के लिए कैश के कई कार्यान्वयन हैं। आप कोडप्लेक्स पर शायद एक दर्जन पा सकते हैं। मुझे लगता है कि आपको इसमें जोड़ने की ज़रूरत है जो कुछ ऐसा है जो एप्लिकेशन के वर्तमान कामकाजी सेट को शुद्ध करने के लिए ट्रिगर के रूप में उपयोग करने के लिए देखता है।

एक और नोट यह है कि आपकी वस्तुओं को इतनी बार क्यों एकत्र किया जा रहा है। जीएन 0 वस्तुओं को साफ करने में जीसी बहुत आक्रामक है। यदि आपकी वस्तुएं बहुत कम रहती हैं (तब तक इसका एकमात्र संदर्भ एक कमजोर संदर्भ है) तो जीसी ऐसा कर रहा है जिसे इसे जितनी जल्दी हो सके सफाई करके किया जा सकता है।

+3

"कोडप्लेक्स पर एक दर्जन" ... और फ्रेमवर्क में से एक। ASP.NET कैश सिस्टम.Web.Caching.Cache गैर-ASP.NET अनुप्रयोगों में उपयोग किया जा सकता है और यह काफी शक्तिशाली है। माइक्रोसॉफ्ट प्रलेखन का कहना है कि इसे क्लाइंट ऐप्स में उपयोग करने की अनुशंसा नहीं की जाती है (लेकिन वास्तव में क्यों नहीं कहती है), लेकिन मैंने इसे विभिन्न प्रकार के ऐप्स में सफलतापूर्वक उपयोग किया है। – Joe

+1

मैंने HttpRuntime.Cache की कोशिश की, लेकिन यह मुझे पसंद नहीं है।मैंने लगातार कैश में आइटम जोड़े और जल्द ही कैश को बेदखल करने के बजाय आउटऑफमेमरी अपवाद मिला। – Rauhotz

+0

"HttpRuntime.Cache, लेकिन यह काम नहीं करता है जैसा कि मुझे पसंद है ... OutOfMemoryException"। आश्चर्य की बात है, लेकिन आप कैश कॉन्फ़िगरेशन को एडजस्ट करने का प्रयास कर सकते हैं - उदा। PrivateBytesLimit और प्रतिशत भौतिक MemoryUsedLimit गुण। या OutOfMemoryException के लिए कुछ और कारण हो सकता है। – Joe

14

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

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

यदि आपके पास अनुमानित हिट रेट पैटर्न हैं, तो मैं वीक रेफरेंस विकल्प से गुजरता हूं और स्पष्ट निष्कासन करता हूं।

+0

समस्या यह है कि जैसे ही मेरे पास एक कैश किए गए ऑब्जेक्ट का मजबूत संदर्भ होता है, मैं इसे संग्रहित के रूप में सेट करने से पहले स्मृति से बाहर चलने का खतरा हूं। – Rauhotz

+2

आपकी बेदखल रणनीति का काम करता है। प्रत्येक कैश को दो मुख्य चीजों की आवश्यकता होती है ... कैश में एक उदाहरण पंजीकृत करने की क्षमता, और एक पृष्ठभूमि प्रक्रिया जो निर्धारित करती है कि नियमों के सेट पर कौन से आइटम बेदखल किए जाने चाहिए। ऐसी कई मौजूदा बेदखल रणनीतियों हैं जो काम कर सकती हैं: एलआरयू (कम हाल ही में प्रयुक्त ... यानी सबसे पुराना आउट), एलएफयू (कम से कम इस्तेमाल किया जाता है ... यानी 10 हिट 100 हिट के साथ वस्तुओं के पक्ष में गिराए जाते हैं), आदि। आप कर सकते हैं हर ऑब्जेक्ट को हमेशा कैश नहीं किया जाता है ... आपको बेदखल करने के लिए पृष्ठभूमि थ्रेड जोड़ना होगा। – jrista

+0

लेकिन वह पृष्ठभूमि धागा कैश को केवल हर समय और फिर अंततः बहुत देर हो जाएगी। – Rauhotz

5

इननेट में, वीक रेफरेंस को जीसी स्टैंडपॉइंट से संदर्भ नहीं माना जाता है, इसलिए किसी भी ऑब्जेक्ट में केवल कमजोर संदर्भ हैं, अगले जीसी रन (उपयुक्त पीढ़ी के लिए) में एकत्र किया जाएगा।

इससे कमजोर संदर्भ कैशिंग के लिए पूरी तरह अनुचित बनाता है - जैसा कि आपका अनुभव दिखाता है।

आपको "वास्तविक" कैश घटक की आवश्यकता है, और कैशिंग के बारे में सबसे महत्वपूर्ण बात यह है कि वहां एक ऐसी निकासी नीति है (यानी, कैश से ऑब्जेक्ट को कब छोड़ना है) के नियम आपके लिए एक अच्छा मैच है आवेदन का उपयोग पैटर्न।

5

एक ऐसी स्थिति है जहां WeakReference-आधारित कैश अच्छा हो सकता है: जब कक्षा में किसी आइटम की उपयोगिता इसके संदर्भ के अस्तित्व पर आधारित होती है। ऐसी स्थिति में, एक कमजोर इंटर्निंग कैश उपयोगी हो सकता है। उदाहरण के लिए, यदि किसी के पास एक ऐसा एप्लिकेशन था जो कई बड़ी अपरिवर्तनीय वस्तुओं को बेकार कर देगा, जिनमें से कई डुप्लीकेट होने की उम्मीद थी, और उन्हें उनके बीच कई तुलना करना होगा। यदि X और Y कुछ अपरिवर्तनीय वर्ग प्रकार के संदर्भ हैं, तो परीक्षण X.Equals(Y) बहुत तेज होगा यदि दोनों चर एक ही उदाहरण को इंगित करते हैं, लेकिन यदि वे अलग-अलग उदाहरणों को इंगित करते हैं तो वे बहुत धीमे हो सकते हैं।यदि एक deserialized ऑब्जेक्ट किसी अन्य ऑब्जेक्ट से मेल खाता है जिसके लिए एक संदर्भ पहले से मौजूद है, तो शब्दकोश से एक बाद वाले ऑब्जेक्ट (एक धीमी तुलना की आवश्यकता) के संदर्भ में भविष्य की तुलना तेज हो सकती है। दूसरी तरफ, यदि यह शब्दकोश में किसी आइटम से मेल खाता है लेकिन शब्दकोश केवल उस आइटम के संदर्भ में था, तो उस वस्तु को संदर्भित करने के बजाय शब्दकोश वस्तु का उपयोग करने के लिए थोड़ा सा फायदा होगा; शायद तुलना की लागत को उचित ठहराने के लिए पर्याप्त लाभ नहीं है। एक आंतरिक कैश के लिए, WeakReferences होने पर जल्द से जल्द अमान्य हो जाएं जब किसी ऑब्जेक्ट में कोई अन्य संदर्भ मौजूद न हो, तो यह एक अच्छी बात होगी।

0

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

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

1

मेरा मानना ​​है कि समस्या आप कर रहे हैं कि कचरा कलेक्टर दुर्बलता से केवल नहीं स्मृति दबाव के जवाब में प्रतिक्रिया में वस्तुओं संदर्भित को दूर करता है - के बजाय यह काफी आक्रामक तरीके से कभी कभी सिर्फ इसलिए क्रम प्रणाली कुछ वस्तुओं सोचता है कि संभावना हो सकता संग्रह करना होगा पहुंचने योग्य नहीं हो गए हैं।

आप उदाहरण का उपयोग कर बेहतर हो सकते हैं System.Runtime.Caching.MemoryCache जिसे स्मृति सीमा के साथ कॉन्फ़िगर किया जा सकता है, या आइटम के लिए कस्टम निष्कासन नीतियां।

0

एक थोड़ी देर हो चुकी है, लेकिन यहां एक प्रासंगिक उपयोग मामला है:

मैं वस्तुओं के दो प्रकार के कैश करने के लिए की जरूरत है: बड़े (deserialised) डेटा है कि 10 मिनट का समय लोड करने के लिए फ़ाइलों और राम प्रत्येक की लागत 15 जी, और छोटे (गतिशील रूप से संकलित) ऑब्जेक्ट्स जिनमें उन डेटा फ़ाइलों के आंतरिक संदर्भ होते हैं (छोटी वस्तुओं को भी कैश किया जाता है क्योंकि वे उत्पन्न करने के लिए ~ 10s लेते हैं)। ये कैश उन कारखानों के भीतर छिपी हुई हैं जो वस्तुओं की आपूर्ति करती हैं (पूर्व घटक को उत्तरार्द्ध का कोई ज्ञान नहीं है), और अलग-अलग बेदखल नीतियां हैं।

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

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