2009-05-09 10 views
42

मैं cProfile का उपयोग कर पायथन में प्रोफाइलिंग कर रहा हूं। मुझे एक ऐसा फ़ंक्शन मिला जो बहुत सी CPU समय लेता है। मैं यह कैसे पता लगा सकता हूं कि कौन सा फ़ंक्शन इस भारी फ़ंक्शन को सबसे ज्यादा कॉल कर रहा है?पायथन में प्रोफाइलिंग: फ़ंक्शन को किसने बुलाया?

संपादित करें:

मैं एक समाधान के लिए समझौता करेंगे: मुझे लगता है कि भारी समारोह है कि समारोह है कि यह कहा जाता है के नाम पर प्रिंट होगा अंदर एक अजगर लाइन लिख सकते हैं?

उत्तर

32

यह आपके प्रश्न का सीधे उत्तर नहीं दे सकता है, लेकिन निश्चित रूप से सहायता करेगा। यदि विकल्प - सॉर्ट संचयी के साथ प्रोफाइलर का उपयोग करें तो यह संचयी समय से कार्यों को सॉर्ट करेगा। जो न केवल भारी कार्यों का पता लगाने में मददगार है बल्कि उन कार्यों को बुलाता है जो उन्हें बुलाते हैं।

python -m cProfile --sort cumulative myScript.py 

वहाँ एक समाधान फोन करने वाले समारोह पाने के लिए है:

import inspect 
print inspect.getframeinfo(inspect.currentframe().f_back)[2] 

के रूप में आप इस मामले में जितने चाहें उतने f_back जोड़ सकते हैं आप चाहते हैं फोन करने वाले कॉलर आदि आपको बार-बार कॉल आप की गणना करना चाहते हैं यह कर सकते हैं:

:

record = {} 

caller = inspect.getframeinfo(inspect.currentframe().f_back)[2] 
record[caller] = record.get(caller, 0) + 1 

फिर उन्हें आवृत्ति के आदेश से प्रिंट

print sorted(record.items(), key=lambda a: a[1]) 
+2

आप एक फाइल करने के लिए cProfile के परिणामों को बचाने और प्रोफ़ाइल को लोड करने के लिए 'pstats' मॉड्यूल का उपयोग करते हैं तो आप सीधे भारी समारोह के कॉल करने के लिए क्वेरी कर सकते हैं:' loaded_stats_object.print_callers ('heavy_function') ' –

1

मैंने स्वयं को सीप्रोफाइल का उपयोग नहीं किया है, लेकिन अधिकांश प्रोफाइलर आपको कॉल पदानुक्रम देते हैं।
गुगलिंग मुझे c12rofile के बारे में यह slides मिला। शायद यह मदद करता है। पृष्ठ 6 सीप्रोफाइल की तरह दिखता है एक पदानुक्रम प्रदान करता है।

+0

लिंक काम नहीं करता है अब और – industryworker3595112

10

inspect.stack() आपको वर्तमान कॉलर स्टैक देगा।

example gprof2dot output

यह यह बहुत करने के लिए आसान बनाता है:

94

मैं लगभग हमेशा Gprof2dot का उपयोग कर cProfile मॉड्यूल के उत्पादन को देखते हैं, मूल रूप से यह एक graphvis ग्राफ में निर्गम (एक .dot फ़ाइल), उदाहरण के लिए धर्मान्तरित निर्धारित करें कि कौन सा फ़ंक्शन सबसे धीमा है, और कौन सा फ़ंक्शन इसे बुलाता है।

प्रयोग है:

python -m cProfile -o output.pstats path/to/your/script arg1 arg2 
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png 
+2

लगता है एक शांत उपकरण की तरह, इसे आजमाएं; ;) – ChristopheD

+2

+1 यह एफ ******** प्रभावशाली और आश्चर्यजनक है! यह मुझे दिखाने के लिए धन्यवाद .. वाह .. –

+0

यदि आप cProfile.run (exp) के साथ एक अभिव्यक्ति प्रोफाइल करना चाहते हैं, तो आप इसका उपयोग कर सकते हैं (अभी भी एक अस्थायी pstats फ़ाइल बनाता है): डिफ़ॉल्ट रन (exp, output = "profile.png", statsFileName = "आँकड़े।pstats "): आयात cProfile cProfile.run (exp, figuresFileName) os.system (" पायथन gprof2dot.py -f pstats% s | dot-tpng -o% s>/dev/null 2> और 1 "% (आँकड़ेफाइलनाम, आउटपुट)) – Ant6n

0

माफ करना, मैं अजगर से परिचित नहीं हूँ, लेकिन वहाँ एक general method कि काम करता है, यह मानते हुए आप मैन्युअल रूप से एक यादृच्छिक समय में निष्पादन बाधित कर सकते हैं।

बस ऐसा करें, और कॉल स्टैक प्रदर्शित करें। यह आपको उच्च संभावना के साथ बताएगा, जिसे आप जानना चाहते हैं। यदि आप अधिक निश्चित होना चाहते हैं, तो बस इसे कई बार करें।

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

नोट: यह प्रक्रिया माप से निदान की तरह अधिक है। मान लीजिए कि बुरी कॉल 90% बर्बाद कर रही है। फिर हर बार जब आप इसे रोकते हैं, तो संभावना 9 0% है कि आपके लिए कॉल स्टैक पर खराब कॉल स्टेटमेंट सही है, और आप यह देख पाएंगे कि यह बुरा है।हालांकि, अगर आप वास्तव में बर्बादी को मापना चाहते हैं, तो यह एक अलग समस्या है। इसके लिए, आपको यह देखने के लिए बहुत अधिक नमूने की आवश्यकता होगी कि उनमें से किस% ​​में कॉल है। या वैकल्पिक रूप से, केवल दोषी कॉल को ठीक करें, गति को घड़ी दें, और यह आपको बताएगा कि बर्बादी क्या थी।

0

पाइस्कोप यह करता है। मैंने अभी इसे आज पाया है, इसलिए मैं यह नहीं कह सकता कि यह कितना अच्छा है, लेकिन मैंने जो कुछ उदाहरण आजमाए हैं, वे बहुत अच्छे हैं (हालांकि सही नहीं हैं)।

https://pypi.python.org/pypi/pycscope/

आप इस का उपयोग एक संपादक, विम विशेष रूप से एक cscope फ़ाइल और फिर एक cscope प्लगइन उत्पन्न करने के लिए होगा। मैंने वेनिला सेस्कोप के साथ इसका उपयोग करने की कोशिश की, ऐसा लगता है कि सादा रस्सी भ्रमित हो जाती है।

0

मानक लाइब्रेरी में प्रोफाइलर cProfile का उपयोग करना संभव है।
pstats.Stats (प्रोफाइलर परिणाम) में विधि print_callees (या वैकल्पिक रूप से print_callers) है।


उदाहरण कोड:

import cProfile, pstats 
pr = cProfile.Profile() 
pr.enable() 

# ... do something ... 

pr.disable() 
ps = pstats.Stats(pr).strip_dirs().sort_stats('cumulative') 
ps.print_callees() 

परिणाम होगा कुछ की तरह:

Function       called... 
             ncalls tottime cumtime 
ElementTree.py:1517(_start_list) -> 24093 0.048 0.124 ElementTree.py:1399(start) 
             46429 0.015 0.041 ElementTree.py:1490(_fixtext) 
             70522 0.015 0.015 ElementTree.py:1497(_fixname) 
ElementTree.py:1527(_data)   -> 47827 0.017 0.026 ElementTree.py:1388(data) 
             47827 0.018 0.053 ElementTree.py:1490(_fixtext) 

छोड़ दिया आप कॉलर है, सही पर आप कॉल प्राप्त करने वाला है पर।
(उदाहरण के _fixtext के लिए _start_list 46,429 बार _data 47,827 काल से और से बुलाया गया था)


यह भी देखें:

  • docs.python.org/..#print_callees - शो कॉल पदानुक्रम। कॉलर द्वारा समूह। (ऊपर इस्तेमाल किया गया)
  • docs.python.org/..#print_callers - कॉल पदानुक्रम दिखाएं। कैली द्वारा समूह।


नोटों की युगल:

  • आपका कोड (उन प्रोफ़ाइल बयान सम्मिलित) इस के लिए संपादित किया जाना चाहिए।
    (यानी संभव नहीं python -m cProfile myscript.py की तरह कमांड लाइन से उपयोग करने के लिए। हालांकि यह संभव है कि के लिए अलग से स्क्रिप्ट लिखने के लिए)
  • थोड़ा असंबंधित, लेकिन strip_dirs() (अन्यथा छँटाई काम नहीं करता है) sort_stats() से पहले जाना चाहिए
+0

इस टिप्पणी में से एक में उल्लेख किया गया था, लेकिन मैंने सोचा कि यह एक अलग उत्तर होने के योग्य है, क्योंकि कभी-कभी बाहरी उपकरण/निर्भरता संभव नहीं होती (भले ही आउटपुट उतना अच्छा न हो, जैसा कि अन्य उत्तरों में) – industryworker3595112

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