मेरे पास एक Django एप्लिकेशन है जो कुछ अजीब कचरा संग्रह व्यवहार प्रदर्शित करता है। विशेष रूप से एक दृश्य है जो हर बार जब इसे बुलाया जाता है तो वीएम आकार को बढ़ाना जारी रखेगा - एक निश्चित सीमा तक, जिस बिंदु पर बिंदु उपयोग फिर से गिर जाता है। समस्या यह है कि उस बिंदु तक पहुंचने में काफी समय लग रहा है, और असल में मेरे ऐप को चलाने वाली वर्चुअल मशीन में सभी एफसीजीआई प्रक्रियाओं के लिए पर्याप्त स्मृति नहीं है जितनी वे कभी-कभी करते हैं।पायथन: कचरा कलेक्टर का व्यवहार
मैंने पिछले दो दिनों में इसकी जांच की है और पाइथन कचरा संग्रह के बारे में सीख लिया है, और मुझे लगता है कि अब मैं समझ रहा हूं कि अब क्या हो रहा है - अधिकांश भाग के लिए। तो अनिवार्य रूप से
>>> c = django.test.Client()
>>> c.get('/the/view/')
gc: collecting generation 0...
gc: objects in each generation: 724 5748 147341
gc: done.
gc: collecting generation 0...
gc: objects in each generation: 731 6460 147341
gc: done.
[...more of the same...]
gc: collecting generation 1...
gc: objects in each generation: 718 8577 147341
gc: done.
gc: collecting generation 0...
gc: objects in each generation: 714 0 156614
gc: done.
[...more of the same...]
gc: collecting generation 0...
gc: objects in each generation: 715 5578 156612
gc: done.
, वस्तुओं की एक बड़ी राशि आवंटित किए जाते हैं, लेकिन शुरू में पीढ़ी 1 करने के लिए ले जाया जाता है, और जब जनरल: जब एक ही अनुरोध के लिए
gc.set_debug(gc.DEBUG_STATS)
का उपयोग कर फिर, मैं निम्नलिखित उत्पादन को देखने के 1 एक ही अनुरोध के दौरान साफ़ हो गया है, वे पीढ़ी 2 में स्थानांतरित हो जाते हैं। यदि मैं मैनुअल gc.collect (2) बाद में करता हूं, तो उन्हें हटा दिया जाता है। और, जैसा कि मैंने उल्लेख किया है, जब भी अगली स्वचालित जीन 2 स्वीप होती है, तो भी हटा दिया जाता है, अगर मैं सही ढंग से समझता हूं, तो इस मामले में प्रत्येक 10 अनुरोधों की तरह कुछ होगा (इस बिंदु पर ऐप को 150 एमबी की आवश्यकता है)।
ठीक है, इसलिए शुरुआत में मैंने सोचा कि एक अनुरोध के प्रसंस्करण के भीतर कुछ चक्रीय संदर्भ हो रहा है जो इन अनुरोधों को संभालने में इन वस्तुओं में से किसी एक को सहेजने से रोकता है। हालांकि, मैंने अनुरोध प्रक्रिया के अंदर और बाद में डिबगिंग के बाद, pympler.muppy और objgraph का उपयोग करके एक खोजने का प्रयास करने में घंटों बिताए हैं, और ऐसा कोई प्रतीत नहीं होता है। इसके बजाय, ऐसा लगता है कि 14.000 ऑब्जेक्ट्स या तो अनुरोध के दौरान बनाए गए हैं, कुछ संदर्भ-वैश्विक वस्तु के संदर्भ में सभी संदर्भ श्रृंखला में हैं, यानी अनुरोध समाप्त होने के बाद, उन्हें मुक्त किया जा सकता है।
यह वैसे भी, यह समझाए जाने का मेरा प्रयास रहा है। हालांकि, यदि यह सच है और वास्तव में कोई साइकिल चालन निर्भरता नहीं है, तो वस्तुओं के पूरे पेड़ को मुक्त नहीं किया जाना चाहिए, जो भी अनुरोध ऑब्जेक्ट होता है जो उन्हें पकड़ने का कारण बनता है, बिना कचरा कलेक्टर के शामिल, पूरी तरह से संदर्भ संख्याओं के आधार पर शून्य पर गिर रहा है?
कि सेटअप के साथ, यहाँ मेरे सवालों हैं:
ऊपर भी कोई मतलब है, या मैं कहीं और समस्या को देखने के लिए है? क्या यह सिर्फ एक दुर्भाग्यपूर्ण दुर्घटना है कि इस विशेष उपयोग के मामले में महत्वपूर्ण डेटा इतने लंबे समय तक रखा जाता है?
क्या इस मुद्दे से बचने के लिए मैं कुछ भी कर सकता हूं। मुझे पहले से ही दृश्य को अनुकूलित करने की कुछ संभावनाएं दिखाई दे रही हैं, लेकिन यह सीमित दायरे के साथ एक समाधान प्रतीत होता है - हालांकि मुझे यकीन नहीं है कि मैं जो सामान्य हूं, वह भी होगा; उदाहरण के लिए gc.collect() या gc.set_threshold() को मैन्युअल रूप से कॉल करने के लिए यह सलाह दी जाती है?
कैसे कचरा कलेक्टर ही काम करता है के संदर्भ में:
मैं सही ढंग से समझ है कि एक वस्तु हमेशा अगली पीढ़ी के लिए ले जाया गया है एक झाड़ू यह देखता है और निर्धारित करता है कि क्या है कि संदर्भ यह चक्रीय नहीं हैं, लेकिन वास्तव में एक मूल वस्तु के लिए पता लगाया जा सकता है।
क्या होगा अगर जीसी एक, कहते हैं, पीढ़ी 1 स्वीप करता है, और एक वस्तु है कि पीढ़ी 2 के भीतर एक वस्तु द्वारा संदर्भित है पाता होता है; क्या यह पीढ़ी 2 के अंदर उस रिश्ते का पालन करता है, या क्या स्थिति का विश्लेषण करने से पहले पीढ़ी 2 स्वीप होने की प्रतीक्षा है?
gc.DEBUG_STATS का उपयोग कर, मैं की जानकारी "हर पीढ़ी में वस्तुओं" के बारे में मुख्य रूप से परवाह; हालांकि, मैं सैकड़ों "जीसी: 0.0740s विलुप्त हो रहा हूं।", "जीसी: 1258233035.9370s समाप्त हो गया।" संदेशों; वे पूरी तरह से असुविधाजनक हैं - उनके लिए मुद्रित होने में काफी समय लगता है, और वे दिलचस्प चीजों को ढूंढना बहुत कठिन बनाते हैं। क्या उनसे छुटकारा पाने का कोई तरीका है?
मुझे नहीं लगता कि पीढ़ी द्वारा gc.get_objects() करने का कोई तरीका है, यानी केवल पीढ़ी 2 से ऑब्जेक्ट्स को पुनर्प्राप्त करें, उदाहरण के लिए?
+1 DEBUG = False सेटिंग का उल्लेख करने के लिए +1 ताकि Django आपके सभी SQL क्वेरी लॉग न करे। – Kekoa
वाह, डैंजो की कितनी मानसिक छवि खाने के लिए खाने का तरीका –