2010-02-02 11 views
12

मैं एक कस्टम फाइल सिस्टम क्रॉलर लिख रहा हूं, जो sys.stdin के माध्यम से प्रक्रिया करने के लिए लाखों ग्लोब पास कर देता है। मुझे लगता है कि स्क्रिप्ट चलाने के दौरान, इसका स्मृति उपयोग समय के साथ बड़े पैमाने पर बढ़ता है और पूरी चीज व्यावहारिक रूप से रुकावट के लिए क्रॉल करती है। मैंने नीचे एक मामला लिखा है जो समस्या दिखाता है। क्या मैं कुछ गलत कर रहा हूं, या क्या मुझे पाइथन/ग्लोब मॉड्यूल में एक बग मिला है? (मैं अजगर 2.5.2 का उपयोग कर रहा हूँ)।मैं इस पायथन लूप के साथ स्मृति क्यों लीक कर रहा हूं?


#!/usr/bin/env python 
import glob 
import sys 
import gc 

previous_num_objects = 0 

for count, line in enumerate(sys.stdin): 
    glob_result = glob.glob(line.rstrip('\n')) 
    current_num_objects = len(gc.get_objects()) 
    new_objects = current_num_objects - previous_num_objects 

    print "(%d) This: %d, New: %d, Garbage: %d, Collection Counts: %s"\ 
% (count, current_num_objects, new_objects, len(gc.garbage), gc.get_count()) 
    previous_num_objects = current_num_objects 

उत्पादन लगता है:

 
(0) This: 4042, New: 4042, Python Garbage: 0, Python Collection Counts: (660, 5, 0) 
(1) This: 4061, New: 19, Python Garbage: 0, Python Collection Counts: (90, 6, 0) 
(2) This: 4064, New: 3, Python Garbage: 0, Python Collection Counts: (127, 6, 0) 
(3) This: 4067, New: 3, Python Garbage: 0, Python Collection Counts: (130, 6, 0) 
(4) This: 4070, New: 3, Python Garbage: 0, Python Collection Counts: (133, 6, 0) 
(5) This: 4073, New: 3, Python Garbage: 0, Python Collection Counts: (136, 6, 0) 
(6) This: 4076, New: 3, Python Garbage: 0, Python Collection Counts: (139, 6, 0) 
(7) This: 4079, New: 3, Python Garbage: 0, Python Collection Counts: (142, 6, 0) 
(8) This: 4082, New: 3, Python Garbage: 0, Python Collection Counts: (145, 6, 0) 
(9) This: 4085, New: 3, Python Garbage: 0, Python Collection Counts: (148, 6, 0) 

हर 100 वीं यात्रा, 100 वस्तुओं को मुक्त कर दिया जाता है, 200 से हर 100 पुनरावृत्तियों तो len(gc.get_objects() बढ़ जाती है। len(gc.garbage) 0 से कभी भी नहीं बदलता है। दूसरी पीढ़ी की संग्रह गणना धीरे-धीरे बढ़ जाती है, जबकि 0 वें और 1 अंक ऊपर और नीचे जाते हैं।

+1

यह uncollected वस्तुओं का एक बहुत जम जाता है। हालांकि, यह रोक नहीं धीमा है, है ना? क्या आप एक समान छोटी लिपि का काम कर सकते हैं जो वास्तव में रुक जाती है? –

उत्तर

2

मैं अपने सिस्टम पर किसी भी वास्तविक रिसाव को पुन: उत्पन्न नहीं कर सकता, लेकिन मुझे लगता है कि आपका "हर 100 वें पुनरावृत्ति, 100 वस्तुओं को मुक्त किया जाता है" क्या आप संकलित नियमित अभिव्यक्तियों (ग्लोब मॉड्यूल के माध्यम से) के लिए कैश को मार रहे हैं। यदि आप re.py पर देखते हैं तो आपको _MAXCACHE 100 पर डिफ़ॉल्ट दिखाई देगा, और डिफ़ॉल्ट रूप से पूरे कैश को उड़ाए जाने के बाद इसे हटा दिया जाएगा (_compile में)। यदि आप पर अपने gc कॉल से पहले कॉल करते हैं तो आप शायद देखेंगे कि प्रभाव दूर हो जाएगा।

(ध्यान दें मैं केवल कि कैश की जाँच करने के लिए अपने जीसी परिणाम को प्रभावित कर रहा re.purge() यहाँ का सुझाव दे रहा हूँ। यह है करने के लिए है कि अपने वास्तविक कोड में आवश्यक नहीं होना चाहिए।)

मुझे शक है कि आपके बड़े पैमाने पर स्मृति वृद्धि समस्या ठीक हो जाती हालांकि।

+0

इसके लिए धन्यवाद - जब मैंने आपके द्वारा सुझाए गए कार्यों को किया, तो प्रभाव वास्तव में दूर चला गया, और नई लूप प्रति लूप 2 में बदल गई। यह स्मृति वृद्धि की समस्या को ठीक नहीं करता है, लेकिन यह निश्चित रूप से यह समझने में जा रहा है कि क्या हो रहा है। – Andy

6

मैंने इसे नीचे fnmatch मॉड्यूल पर ट्रैक किया। glob.glob वास्तव में globbing प्रदर्शन करने के लिए fnmatch कहते हैं, और fnmatch नियमित अभिव्यक्तियों का एक कैश है जो कभी भी मंजूरी नहीं दी जाती है। तो इस उपयोग में, कैश लगातार बढ़ रहा था और अनचेक किया गया था। मैंने fnmatch लाइब्रेरी [1] के खिलाफ एक बग दायर किया है।

[1]: http://bugs.python.org/issue7846 अजगर बग

+0

मुझे आश्चर्य है कि मैं फिर से मॉड्यूल में इसी तरह के कैश को कैसे खोज सकता था लेकिन यह नहीं! शायद मुझे इसके लिए अपने उत्तर से एक बिंदु घटा देना चाहिए ... – mzz

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