2010-10-12 22 views
15

मैं अपने अजगर आवेदन के साथ एक समस्या है, और मुझे लगता है कि यह अजगर कचरा संग्रहण से संबंधित है, भले ही मैं सुनिश्चित नहीं हूं ...पायथन कचरा संग्रह धीमा हो सकता है?

समस्या यह है कि अपने आवेदन और बाहर निकलने के लिए बहुत समय लेता है अगले एक को एक समारोह में स्विच करने के लिए।

मेरे आवेदन में मैं बहुत बड़े शब्दकोशों को संभालता हूं, जिनमें हजारों बड़ी वस्तुएं होती हैं जिन्हें लपेटा हुआ सी ++ कक्षाओं से तुरंत चालू किया जाता है।

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

स्मृति उपयोग स्थिर है, इसलिए मेरे पास वास्तव में स्मृति रिसाव नहीं है।

कोई सुझाव?

हजारों बड़ी सी ++ ऑब्जेक्ट्स का कचरा संग्रह धीमा हो सकता है जो धीमा हो?

क्या इसे गति देने के लिए कोई तरीका है?

अद्यतन:

धन्यवाद अपने सभी उत्तरों के लिए एक बहुत, आप मुझे संकेत का एक बहुत :-)

मैं वैज्ञानिक लिनक्स 5, पर अजगर 2.6.5 का उपयोग अपने कोड डिबग करने के लिए दिया एक Red Hat Enterprise 5. पर आधारित अनुकूलित वितरण और वास्तव में मैं अपने सी ++ कोड के लिए पाइथन बाइंडिंग प्राप्त करने के लिए SWIG का उपयोग नहीं कर रहा हूं, लेकिन रिफ्लेक्स/पायरोट फ्रेमवर्क। मुझे पता है, यह कण भौतिकी के बाहर बहुत ज्ञात नहीं है (लेकिन अभी भी खुला स्रोत और स्वतंत्र रूप से उपलब्ध है) और मुझे इसका उपयोग करना होगा क्योंकि यह हमारे मुख्य ढांचे के लिए डिफ़ॉल्ट है।

और इस संदर्भ में पायथन पक्ष से DEL आदेश काम नहीं करता है, मैंने पहले ही इसे आजमाया था। डीएल केवल सी ++ ऑब्जेक्ट से जुड़े पायथन वैरिएबल को हटा देता है, न कि वस्तु को स्मृति में, जो अभी भी सी ++ पक्ष के स्वामित्व में है ...

... मुझे पता है, यह मानक नहीं है, और थोड़ा सा जटिल, क्षमा करें :-P

लेकिन आपके संकेतों का पालन करते हुए, मैं अपना कोड प्रोफाइल करूंगा और जैसा कि आपने सुझाव दिया है, मैं आपको अधिक जानकारी के साथ वापस आऊंगा।

अतिरिक्त अद्यतन:

ठीक है, आपके सुझावों का पालन, मैं अपने कोड cProfile साथ instrumented, और मुझे पता चला कि वास्तव में gc.collect() समारोह समारोह चल रहा है समय के सबसे अधिक ले जा रहा है !!

यहाँ cProfile + pstats print_stats() से उत्पादन:

 

    >>> p.sort_stats("time").print_stats(20) 
Wed Oct 20 17:46:02 2010 mainProgram.profile 

     547303 function calls (542629 primitive calls) in 548.060 CPU seconds 

    Ordered by: internal time 
    List reduced from 727 to 20 due to restriction 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     4 345.701 86.425 345.704 86.426 {gc.collect} 
     1 167.115 167.115 200.946 200.946 PlotD3PD_v3.2.py:2041(PlotSamplesBranches) 
     28 12.817 0.458 13.345 0.477 PlotROOTUtils.py:205(SaveItems) 
    9900 10.425 0.001 10.426 0.001 PlotD3PD_v3.2.py:1973(HistoStyle) 
    6622 5.188 0.001 5.278 0.001 PlotROOTUtils.py:403(__init__) 
     57 0.625 0.011 0.625 0.011 {built-in method load} 
     103 0.625 0.006 0.792 0.008 dbutils.py:41(DeadlockWrap) 
     14 0.475 0.034 0.475 0.034 {method 'dump' of 'cPickle.Pickler' objects} 
    6622 0.453 0.000 5.908 0.001 PlotROOTUtils.py:421(CreateCanvas) 
    26455 0.434 0.000 0.508 0.000 /opt/root/lib/ROOT.py:215(__getattr__) 
[...] 

>>> p.sort_stats("cumulative").print_stats(20) 
Wed Oct 20 17:46:02 2010 mainProgram.profile 

     547303 function calls (542629 primitive calls) in 548.060 CPU seconds 

    Ordered by: cumulative time 
    List reduced from 727 to 20 due to restriction 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.001 0.001 548.068 548.068 PlotD3PD_v3.2.py:2492(main) 
     4 0.000 0.000 346.756 86.689 /usr/lib//lib/python2.5/site-packages/guppy/heapy/Use.py:171(heap) 
     4 0.005 0.001 346.752 86.688 /usr/lib//lib/python2.5/site-packages/guppy/heapy/View.py:344(heap) 
     1 0.002 0.002 346.147 346.147 PlotD3PD_v3.2.py:2537(LogAndFinalize) 
     4 345.701 86.425 345.704 86.426 {gc.collect} 
     1 167.115 167.115 200.946 200.946 PlotD3PD_v3.2.py:2041(PlotBranches) 
     28 12.817 0.458 13.345 0.477 PlotROOTUtils.py:205(SaveItems) 
    9900 10.425 0.001 10.426 0.001 PlotD3PD_v3.2.py:1973(HistoStyle) 
    13202 0.336 0.000 6.818 0.001 PlotROOTUtils.py:431(PlottingCanvases) 
    6622 0.453 0.000 5.908 0.001 /root/svn_co/rbianchi/SoftwareDevelopment 

[...] 

>>> 

तो, दोनों आउटपुट, "समय" से और "संचयी" समय क्रमशः के अनुसार क्रमबद्ध में, gc.collect() समारोह के सबसे लगता है मेरे कार्यक्रम का समय चल रहा है!:- पी

और यह main() प्रोग्राम लौटने से ठीक पहले, स्मृति प्रोफाइलर Heapy का आउटपुट है।

 
memory usage before return: 
Partition of a set of 65901 objects. Total size = 4765572 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 25437 39 1452444 30 1452444 30 str 
    1 6622 10 900592 19 2353036 49 dict of PlotROOTUtils.Canvas 
    2 109 0 567016 12 2920052 61 dict of module 
    3 7312 11 280644 6 3200696 67 tuple 
    4 6622 10 238392 5 3439088 72 0xa4ab74c 
    5 6622 10 185416 4 3624504 76 PlotROOTUtils.Canvas 
    6 2024 3 137632 3 3762136 79 types.CodeType 
    7 263 0 129080 3 3891216 82 dict (no owner) 
    8 254 0 119024 2 4010240 84 dict of type 
    9 254 0 109728 2 4119968 86 type 
    Index Count %  Size % Cumulative % Kind (class/dict of class) 
    10 1917 3 107352 2 4264012 88 function 
    11 3647 5 102116 2 4366128 90 ROOT.MethodProxy 
    12 148 0 80800 2 4446928 92 dict of class 
    13 1109 2 39924 1 4486852 93 __builtin__.wrapper_descriptor 
    14 239 0 23136 0 4509988 93 list 
    15  87 0 22968 0 4532956 94 dict of guppy.etc.Glue.Interface 
    16 644 1 20608 0 4553564 94 types.BuiltinFunctionType 
    17 495 1 19800 0 4573364 94 __builtin__.weakref 
    18  23 0 11960 0 4585324 95 dict of guppy.etc.Glue.Share 
    19 367 1 11744 0 4597068 95 __builtin__.method_descriptor 

कोई विचार क्यों, या कचरा संग्रह को अनुकूलित करने के लिए कैसे?

क्या कोई और विस्तृत जांच है जो मैं कर सकता हूं?

+9

"कोई सुझाव?"। समय बिताया जा रहा है पर अधिक तथ्यों के लिए प्रोफाइलर का प्रयोग करें। परिणामों को अपने प्रश्न के अपडेट के रूप में पोस्ट करें। –

+0

@nos: असल में, पायथन रीफ्रैंटिंग का उपयोग करता है, इसलिए एक अपरिवर्तित ऑब्जेक्ट * एकत्र किया जाएगा। पाइथन जीसी अच्छे जेवीएम और .NET में चालाक जानवरों की तुलना में अपेक्षाकृत सरल है। – delnan

+0

@ डेलन सटीक होने के लिए, सीपीथन के कार्यान्वयन में वह व्यवहार है। मुझे लगता है कि कुछ प्रयोगात्मक संस्करणों को बहुत प्रशंसक एल्गोरिदम के साथ याद किया जाता है। –

उत्तर

7

This is known garbage collector issue in Python 2.6 कचरा संग्रह के लिए वर्गबद्ध समय पैदा करता है जब कई वस्तुओं को उनमें से किसी भी को हटाए बिना आवंटित किया जाता है। बड़ी सूची की जनसंख्या।
दो सरल समाधान कर रहे हैं:

  1. या तो बड़े सूचियों को आबाद करने से पहले अक्षम कचरा संग्रहण और बाद में

    l = [] 
    gc.disable() 
    for x in xrange(10**6): 
        l.append(x) 
    gc.enable() 
    
  2. या Python 2.7, where the issue has been solved

को अद्यतन इसे सक्षम मेरी विनती है दूसरे समाधान को फेर करें, लेकिन यह हमेशा एक विकल्प नहीं है;)

6

हां, यह कचरा संग्रह हो सकता है, लेकिन यह सी ++ कोड के साथ कुछ सिंक्रनाइज़ेशन भी हो सकता है, या कुछ पूरी तरह अलग हो सकता है (कोड के बिना कहना मुश्किल है)।

वैसे भी, आपको समस्याओं को ढूंढने और चीजों को गति देने के लिए SIG for development of Python/C++ integration पर एक नज़र रखना चाहिए।

+0

हाय क्रिस, जाहिर है कि इसमें कचरा कलेक्टर समस्या है। मैंने सीपीरोफाइल के आउटपुट के साथ अपना प्रश्न अपडेट किया, और ऐसा लगता है कि gc.collect सबसे अधिक समय चल रहा है ... जैसा कि आपने सुझाव दिया है, मैं एसआईजी पायथन/सी ++ पर एक नज़र डालेगा, यह देखने के लिए कि यह एक है या नहीं कुछ संदर्भों में ज्ञात समस्या। – rmbianchi

+0

कच्ची शर्त: जीसी शायद ऐसे मामले में है जहां refcounting अच्छी तरह से काम नहीं करता है (स्मृति को पुनः प्राप्त करने के लिए एक और जटिल रणनीति का उपयोग करना है)। आपकी डेटा संरचना में कोई लूप (चक्रीय संदर्भ)? यदि यह "हाथ से" काटने में समस्या का स्रोत हो सकता है तो यह एक समाधान हो सकता है, यह जीसी को खुश कर देगा (इसलिए तेज़)। – kriss

-3

यदि आपकी समस्या वास्तव में कचरा संग्रह है, तो del() का उपयोग करके उनके साथ किए जाने पर स्पष्ट रूप से अपनी वस्तुओं को मुक्त करने का प्रयास करें।

सामान्यतः, यह कचरा संग्रहण समस्या की तरह नहीं लगता है, जब तक कि हम स्मृति के टेराबाइट्स के बारे में बात नहीं कर रहे हों।

मैं एसएलओटी से सहमत हूं ... अपने ऐप को प्रोफाइल करें, फिर कोड स्निपेट और उसके पीछे के परिणाम लाएं और हम और अधिक सहायक हो सकते हैं।

+2

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

+0

सामान्य रूप से, हां। पैथोलॉजिकल मामले में, छोटे टुकड़ों को मुक्त करने में मदद मिल सकती है। आदत से पूरे स्थान पर 'डेल' का उपयोग करना एक संकेत है जो आप पाइथन में प्रोग्रामिंग नहीं कर रहे हैं। –

+0

धन्यवाद, पॉल और डेलनान। असल में मैंने डेल() का उपयोग करने की भी कोशिश की, लेकिन इस संदर्भ में काम नहीं करता है। जैसा कि मैंने अपने प्रश्न के अपडेट में बताया था, मैं रूट (http://root.cern.ch) नामक एक ओपन सोर्स फ्रेमवर्क का उपयोग कर रहा हूं, जिसमें अपनी पाइथन बाइंडिंग सिस्टम (रिफ्लेक्स कहा जाता है), और यहां तक ​​कि यदि डेल() हटा देता है एक सी ++ ऑब्जेक्ट के सभी पायथन संदर्भ, ऑब्जेक्ट स्वयं स्मृति में रहता है ... लेकिन फिर भी मुझे उन्हें स्पष्ट रूप से हटाने के लिए एक तरीका मिला है, gc.collect फ़ंक्शन सबसे अधिक समय चल रहा है ... आगे की जांच के लिए कोई सुझाव? आपकी मदद के लिए बहुत बहुत धन्यवाद – rmbianchi

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