पायथन मेमोरी लीक [बंद]


180

मेरे पास एक लंबी चलने वाली स्क्रिप्ट है, जो अगर लंबे समय तक चलने दें, तो मेरे सिस्टम पर सभी मेमोरी का उपभोग करेगा।

स्क्रिप्ट के बारे में जानकारी के बिना, मेरे दो सवाल हैं:

  1. क्या कोई "बेस्ट प्रैक्टिस" का पालन करना है, जो लीक होने से रोकने में मदद करेगा?
  2. पायथन में मेमोरी लीक को डिबग करने के लिए क्या तकनीकें हैं?

5
मुझे यह नुस्खा मददगार लगा है।
डेविड शाहीन

यह उपयोगी होने के लिए बहुत अधिक डेटा का प्रिंट आउट लगता है
केसबश

1
@ कैसबैश: यदि वह फ़ंक्शन कुछ भी प्रिंट करता है तो आप इसे गंभीरता से गलत कर रहे हैं। यह उन __del__विधियों के साथ वस्तुओं को सूचीबद्ध करता है जो अब उनके चक्र को छोड़कर संदर्भित नहीं हैं। समस्याओं के कारण, चक्र को तोड़ा नहीं जा सकता __del__। इसे ठीक करो!
हेल्मुट ग्रोहेन 14

जवाबों:


106

इस लेख पर एक नज़र डालें: अनुरेखण अजगर स्मृति लीक

इसके अलावा, ध्यान दें कि कचरा संग्रह मॉड्यूल वास्तव में डीबग ध्वज सेट हो सकता है। को देखो set_debugसमारोह। इसके अतिरिक्त, कॉल के बाद बनाई गई वस्तुओं के प्रकार को निर्धारित करने के लिए Gnibbler द्वारा इस कोड को देखें


83

मैंने पहले बताए गए अधिकांश विकल्पों की कोशिश की, लेकिन इस छोटे और सहज ज्ञान युक्त पैकेज को सबसे अच्छा पाया: pympler

यह उन वस्तुओं को ट्रेस करने के लिए बहुत सीधा है जो कचरा एकत्र नहीं थे, इस छोटे से उदाहरण की जाँच करें:

के माध्यम से पैकेज स्थापित करें pip install pympler

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

आउटपुट आपको उन सभी ऑब्जेक्ट्स को दिखाता है जो जोड़े गए हैं, साथ ही वे मेमोरी का उपभोग करते हैं।

नमूना उत्पादन:

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

यह पैकेज कई और सुविधाएँ प्रदान करता है। विशेष रूप से स्मृति लीक की पहचान करने वाले अनुभाग में, झाँकी के प्रलेखन की जाँच करें ।


5
यह ध्यान देने योग्य है कि धीमीpympler हो सकती है । यदि आप कुछ अर्ध-वास्तविक समय कर रहे हैं, तो यह आपके आवेदन के प्रदर्शन को पूरी तरह से अपंग कर सकता है।
नकली नाम

@sebpiq ने अजीब तरह से कहा, मेरे साथ भी ऐसा ही होता है ... क्या आपको कुछ पता है कि ऐसा क्यों हो रहा है? स्रोत कोड पर एक त्वरित नज़र ने कोई वास्तविक जानकारी नहीं दी।
लिनसग

25

मुझे मेरे द्वारा बनाए गए मेम_टॉप टूल की सलाह दें

इसने मुझे एक समान मुद्दे को हल करने में मदद की

यह सिर्फ तुरंत पायथन कार्यक्रम में मेमोरी लीक के लिए शीर्ष संदिग्धों को दिखाता है


1
यह सच है ... लेकिन यह उपयोग / परिणाम की व्याख्या के तरीके में बहुत कम देता है
me_

@me_, इस टूल में प्रलेखित "उपयोग" और "स्पष्टीकरण परिणाम" दोनों अनुभाग हैं। क्या मुझे इस तरह की व्याख्या जोड़नी चाहिए जैसे "रेफ्स ऑब्जेक्ट से संदर्भों की गिनती है, प्रकार इस प्रकार की वस्तुओं की गणना है, बाइट्स ऑब्जेक्ट का आकार है" - क्या यह दस्तावेज़ के लिए बहुत स्पष्ट नहीं होगा?
डेनिस रयज़्कोव

टूल का उपयोग डॉक्स एक एकल लाइन देता है जो कहती है "समय-समय पर: logging.debug (mem_top ())", जबकि इसके परिणामों की व्याख्या लेखक की वास्तविक जीवन त्रुटि संदर्भ के बिना ट्रैकिंग अनुभव है ... जो एक तकनीकी विनिर्देश नहीं है जो बताता है एक देव वास्तव में वे क्या देख रहे हैं ... मैं आपका जवाब नहीं दे रहा हूँ ... यह उच्च स्तर के संदिग्धों को बिल के रूप में दिखाता है ... यह उपयोग के परिणाम को पूरी तरह से समझने के लिए पर्याप्त दस्तावेज नहीं देता है ... उदाहरण के लिए , "समझाते हुए परिणाम" आउटपुट में "गियरमैनजोब्रेस्टेस्ट" स्पष्ट रूप से एक समस्या क्यों है? कोई स्पष्टीकरण क्यों ...
me_

1
मैं लगता है कि मैं अनजाने में अपने उपकरण दस्तक रहा हूँ, अगर आप लेखक हैं ... कोई अपराध करना था ...
me_

6
@me_, मैंने बस "उपयोग" के लिए अगला चरण जोड़ा है, "काउंटरर्स" अनुभाग जोड़ा, स्पष्टीकरण दिया कि वास्तव में गियरमैन उस वास्तविक जीवन उदाहरण में एक संदिग्ध क्यों था, कोड में "मेम_टॉप ()" के प्रत्येक वैकल्पिक पैरामीटर को प्रलेखित किया, और यह सब v0.1.7 के रूप में अपलोड किया गया है - कृपया कुछ और सुधार करें। धन्यवाद! )
डेनिस रयज़्कोव

18

Tracemalloc मॉड्यूल Python 3.4 से शुरू होने वाले अंतर्निहित मॉड्यूल के रूप में एकीकृत किया गया था, और जाहिर है, यह तीसरे पक्ष के पुस्तकालय के रूप में पायथन के पूर्व संस्करणों के लिए भी उपलब्ध है (हालांकि इसका परीक्षण नहीं किया है)।

यह मॉड्यूल उन सटीक फ़ाइलों और लाइनों को आउटपुट करने में सक्षम है जो सबसे अधिक मेमोरी आवंटित करते हैं। IMHO, यह जानकारी प्रत्येक प्रकार के लिए आवंटित आवृत्तियों की संख्या की तुलना में असीम रूप से अधिक मूल्यवान है (जो अंत में 99% ट्यूपल्स का एक बहुत कुछ हो रहा है, जो एक सुराग है, लेकिन ज्यादातर मामलों में मुश्किल से मदद करता है)।

मैं तुम्हारे साथ संयोजन में tracemalloc का उपयोग करें pyrasite । 10 में से 9 बार, पायरसाइट-शेल में शीर्ष 10 स्निपेट को चलाने से आपको 10 मिनट के भीतर रिसाव को ठीक करने के लिए पर्याप्त जानकारी और संकेत मिलेंगे। फिर भी, यदि आप अभी भी रिसाव के कारण को खोजने में असमर्थ हैं, तो इस धागे में वर्णित अन्य उपकरणों के साथ संयोजन में पाइरसाइट-शेल शायद आपको कुछ और संकेत भी देगा। आपको पायरसाइट (जैसे स्मृति दर्शक) द्वारा प्रदान किए गए सभी अतिरिक्त सहायकों पर भी एक नज़र डालनी चाहिए।



12

आपको विशेष रूप से अपने वैश्विक या स्थिर डेटा (लंबे समय तक रहने वाले डेटा) पर एक नज़र रखना चाहिए।

जब यह डेटा प्रतिबंध के बिना बढ़ता है, तो आप पायथन में भी परेशानी उठा सकते हैं।

कचरा संग्रहकर्ता केवल डेटा एकत्र कर सकता है, जिसे किसी भी अधिक संदर्भित नहीं किया जाता है। लेकिन आपका स्थैतिक डेटा डेटा तत्वों को हुक कर सकता है जिन्हें मुक्त किया जाना चाहिए।

एक अन्य समस्या मेमोरी साइकल हो सकती है, लेकिन कम से कम सिद्धांत में गारबेज कलेक्टर को चक्रों को ढूंढना और समाप्त करना चाहिए - कम से कम जब तक वे कुछ लंबे जीवित डेटा पर झुके नहीं होते हैं।

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


7

लंबे समय तक चलने वाली प्रक्रियाओं के लिए मेमोरी लीक का पता लगाने और उसका पता लगाने के लिए, जैसे उत्पादन वातावरण में, अब आप स्टैम्पिम्पैक्ट का उपयोग कर सकते हैं । यह नीचे ट्रेसमैलोक का उपयोग करता है। अधिक जानकारी इस पोस्ट में

यहां छवि विवरण दर्ज करें


4

जहां तक ​​सर्वोत्तम प्रथाओं का है, पुनरावर्ती कार्यों के लिए नज़र रखें। मेरे मामले में मैं पुनरावृत्ति (जहां होने की आवश्यकता नहीं थी) के साथ मुद्दों में भाग गया। मैं क्या कर रहा था का एक सरल उदाहरण:

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

इस पुनरावर्ती तरीके से कार्य करना कचरा संग्रह को ट्रिगर नहीं करेगा और फ़ंक्शन के अवशेषों को साफ कर देगा, इसलिए हर बार मेमोरी उपयोग के माध्यम से बढ़ रहा है और बढ़ रहा है।

मेरा समाधान my_function () से पुनरावर्ती कॉल को खींचना था और इसे फिर से कॉल करने के लिए मुख्य () हैंडल होना चाहिए। इस तरह से कार्य स्वाभाविक रूप से समाप्त हो जाता है और स्वयं के बाद साफ हो जाता है।

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()

7
यदि आप पुनरावृत्ति की गहराई सीमा से टकराते हैं तो इस तरीके से पुनरावृत्ति का उपयोग करना भी बंद हो जाएगा क्योंकि पायथन पूंछ कॉल को अनुकूलित नहीं करता है। डिफ़ॉल्ट रूप से, यह 1000 पुनरावर्ती कॉल है।
रेयान

3

अजगर में मेमोरी लीक के लिए "सर्वश्रेष्ठ अभ्यास" के बारे में निश्चित नहीं है, लेकिन अजगर को यह स्पष्ट करना चाहिए कि यह कचरा कलेक्टर द्वारा स्वयं की स्मृति है। इसलिए मुख्य रूप से मैं कुछ शॉर्ट की परिपत्र सूची की जांच करके शुरू करूंगा, क्योंकि वे कचरा कलेक्टर द्वारा नहीं उठाए जाएंगे।


3
या उन वस्तुओं के संदर्भ जो हमेशा के लिए रखे जा रहे हैं, आदि
मैट बी

3
क्या आप लोग परिपत्र सूचियों और उन वस्तुओं के उदाहरण प्रदान कर सकते हैं जिन्हें हमेशा के लिए रखा जा रहा है?
डैनियल

2

यह बिना किसी सलाह के होता है। लेकिन भविष्य की मेमोरी लीक (लूप्स) से बचने के विचार के साथ लिखते समय ध्यान में रखने वाली एक बात यह सुनिश्चित करना है कि जो भी कॉल-बैक के संदर्भ को स्वीकार करता है, उस कॉल-बैक को एक कमजोर संदर्भ के रूप में संग्रहीत करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.