2011-01-25 15 views
8

क्या पाइथन में एक मल्टीथ्रेड प्रोग्राम की प्रोफाइल मेमोरी करने का कोई तरीका है?मैं पाइथन में मल्टीथ्रेड प्रोग्राम की मेमोरी कैसे प्रोफाइल कर सकता हूं?

सीपीयू प्रोफाइलिंग के लिए, मैं प्रत्येक थ्रेड के लिए पृथक प्रोफाइलर आंकड़े बनाने के लिए cprrofile का उपयोग कर रहा हूं और बाद में उन्हें गठबंधन करता हूं। हालांकि, मुझे स्मृति प्रोफाइलर्स के साथ ऐसा करने का कोई तरीका नहीं मिला। मैं ढेर का उपयोग कर रहा हूँ।

क्या सीप्रोफाइल की तरह ढेर में आंकड़ों को गठबंधन करने का कोई तरीका है? या आप अन्य मेमोरी प्रोफाइलर्स का सुझाव देंगे जो इस कार्य के लिए अधिक उपयुक्त है।

इससे संबंधित एक सवाल बहु धागा कार्यक्रम से अधिक CPU उपयोग रूपरेखा के लिए कहा गया था: How can I profile a multithread program in Python?

इसके अलावा स्मृति प्रोफाइलर के बारे में एक और सवाल: Python memory profiler

+0

आप उन अन्य प्रश्नों के समाधानों के बारे में क्या पसंद नहीं करते हैं? – Falmarri

+0

@ फाल्मररी, मैं एक 'मेमोरी' प्रोफाइलर की तलाश में हूं। पहला मुख्य रूप से एक सीपीयू प्रोफाइलर है। दूसरा एक केवल एक धागे के लिए काम करता है। –

+1

धागे की मुख्य विशेषता यह है कि वे स्मृति साझा करते हैं (प्रक्रियाओं के विपरीत)। आप सभी समान स्मृति साझा करने वाले धागे के लिए अलग-अलग मेमोरी आंकड़ों को प्रोफ़ाइल करने की अपेक्षा कैसे करते हैं? – scoffey

उत्तर

7

यदि आप कच्चे मेमोरी की बजाय ऑब्जेक्ट्स प्रोफाइल करने में खुश हैं, तो आप gc.get_objects() फ़ंक्शन का उपयोग कर सकते हैं ताकि आपको कस्टम मेटाक्लास की आवश्यकता न हो। हाल ही में पाइथन संस्करणों में, sys.getsizeof() आपको यह पता लगाने में एक शॉट भी देगा कि उन वस्तुओं द्वारा अंतर्निहित स्मृति कितनी उपयोग में है।

+0

यह बहुत अच्छा है। मेरे दृष्टिकोण से बहुत साफ है। –

3

तरीके अजगर कार्यक्रमों की स्मृति प्रोफ़ाइल valgrind प्राप्त करने के लिए कर रहे हैं: http://www.python.org/dev/faq/#can-i-run-valgrind-against-python

+0

पहले कभी वाल्ग्रिंड के बारे में नहीं सुना; निश्चित रूप से इसे जांच लेंगे। –

+0

@funktku यह मेमोरी उपयोग प्रोफाइलिंग और मेमोरी लीक का पता लगाने के लिए एक मानक उपकरण है। –

1

ठीक है। जो मैं वास्तव में खोज रहा था वह अस्तित्व में प्रतीत नहीं होता है। इसलिए, मुझे एक समाधान मिला - इस समस्या के लिए एक समाधान।

मेमोरी प्रोफाइल करने के बजाय, मैं ऑब्जेक्ट्स प्रोफाइल करूंगा। इस तरह, मैं देख सकता हूं कि कार्यक्रम में किसी विशिष्ट समय पर कितनी वस्तुएं मौजूद हैं। मेरे लक्ष्य को प्राप्त करने के लिए, मैंने मेटाक्लास का उपयोग पहले से ही मौजूदा कोड में न्यूनतम संशोधन के साथ किया है।

निम्नलिखित मेटाक्लास क्लास के __init__ और __del__ कार्यों में एक बहुत ही सरल सबराउटिन जोड़ता है। __init__ के लिए उपरोटाइन उस वर्ग के नाम के साथ वस्तुओं की संख्या को एक से बढ़ाता है और __del__ एक से कम हो जाता है।

class ObjectProfilerMeta(type): 
    #Just set metaclass of a class to ObjectProfilerMeta to profile object 
    def __new__(cls, name, bases, attrs): 
     if name.startswith('None'): 
      return None 

     if "__init__" in attrs: 
      attrs["__init__"]=incAndCall(name,attrs["__init__"]) 
     else: 
      attrs["__init__"]=incAndCall(name,dummyFunction) 

     if "__del__" in attrs: 
      attrs["__del__"]=decAndCall(name,attrs["__del__"]) 
     else: 
      attrs["__del__"]=decAndCall(name,dummyFunction) 

     return super(ObjectProfilerMeta, cls).__new__(cls, name, bases, attrs) 

    def __init__(self, name, bases, attrs): 
     super(ObjectProfilerMeta, self).__init__(name, bases, attrs) 


    def __add__(self, other): 
     class AutoClass(self, other): 
      pass 
     return AutoClass 

incAndCall और decAndCall फ़ंक्शंस उन मॉड्यूल के वैश्विक चर का उपयोग करने का उपयोग करते हैं।

counter={} 
def incAndCall(name,func): 
    if name not in counter: 
     counter[name]=0 

    def f(*args,**kwargs): 
     counter[name]+=1 
     func(*args,**kwargs) 

    return f 

def decAndCall(name,func): 
    if name not in counter: 
     counter[name]=0 

    def f(*args,**kwargs): 
     counter[name]-=1 
     func(*args,**kwargs) 

    return f 

def dummyFunction(*args,**kwargs): 
    pass 

डमीफंक्शन केवल एक बहुत ही सरल कामकाज है। मुझे यकीन है कि ऐसा करने के लिए बेहतर तरीके हैं।

अंत में, जब भी आप मौजूद वस्तुओं की संख्या देखना चाहते हैं, तो आपको काउंटर डिक्शनरी को देखने की आवश्यकता है। एक उदाहरण;

>>> class A: 
    __metaclass__=ObjectProfilerMeta 
    def __init__(self): 
     pass 


>>> class B: 
    __metaclass__=ObjectProfilerMeta 


>>> l=[] 
>>> for i in range(117): 
    l.append(A()) 


>>> for i in range(18): 
    l.append(B()) 


>>> counter 
{'A': 117, 'B': 18} 
>>> l.pop(15) 
<__main__.A object at 0x01210CB0> 
>>> counter 
{'A': 116, 'B': 18} 
>>> l=[] 
>>> counter 
{'A': 0, 'B': 0} 

मुझे आशा है कि यह आपकी मदद करेगा। यह मेरे मामले के लिए पर्याप्त था।

0

मैंने Yappi का उपयोग किया है, जिसे मैंने कुछ विशेष बहु-थ्रेडेड मामलों के लिए सफलता मिली है। यह बहुत अच्छा प्रलेखन है इसलिए आपको इसे स्थापित करने में बहुत अधिक परेशानी नहीं होनी चाहिए।

मेमोरी विशिष्ट प्रोफाइलिंग के लिए, Heapy देखें। चेतावनी दीजिये, यह आपके द्वारा कभी देखी गई सबसे बड़ी लॉग फ़ाइलों में से कुछ बना सकता है!

+0

दुर्भाग्य से मैं इन दोनों प्रोफाइलरों से अवगत हूं और संबंधित प्रश्नों के लिंक दिए हैं जो विशेष रूप से याप्पी और हेपी के बारे में बात करते हैं। समस्या यह है कि, यप्पी मेमोरी प्रोफाइल नहीं करता है और हेपी केवल मुख्य धागे मेमोरी उपयोग को प्रोफाइल करता है (अधिक सटीक थ्रेड जिसे इसे से बुलाया जाता है)। –

+0

@ कुशलप। मैंने यापाई की कोशिश की, मुझे लगता है कि यह मेरे लाइन-दर-लाइन निष्पादन समय नहीं दे सकता है। क्या मुझे कुछ याद आती है? –

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