سؤال

غالبا ما يكون لدى Project Euler ومسابقات الترميز الأخرى في كثير من الأحيان الحد الأقصى للتشغيل أو الأشخاص الذين يتباهون مدى سرعة تشغيل حلها الخاص. مع بيثون، في بعض الأحيان الأساليب هي kludgey إلى حد ما - أي إضافة رمز التوقيت إلى __main__.

ما هو وسيلة جيدة إلى الملف الشخصي كم من الوقت يستغرق برنامج Python لتشغيل؟

هل كانت مفيدة؟

المحلول

يضم بيثون منشأا cprofile.. وبعد لا يوفر فقط إجمالي وقت التشغيل، ولكن أيضا تايمز كل وظيفة بشكل منفصل، ويخبرك بعدد المرات التي تم فيها استدعاء كل وظيفة، مما يجعل من السهل تحديد المكان الذي يجب أن تصدر فيه التحسينات.

يمكنك الاتصال به من داخل التعليمات البرمجية الخاصة بك، أو من المترجم، مثل هذا:

import cProfile
cProfile.run('foo()')

حتى أكثر فائدة، يمكنك استدعاء CProfile عند تشغيل البرنامج النصي:

python -m cProfile myscript.py

لجعلها أسهل، قمت بإجراء ملف دفعي صغير يسمى "الملف الشخصي .bat":

python -m cProfile %1

لذلك كل ما علي فعله هو تشغيل:

profile euler048.py

وأحصل على هذا:

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 <string>:1(<module>)
 1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)
    1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

تحرير: تحديث الرابط إلى مورد فيديو جيد من PYCON 2013 بعنوانبيثون التنميط
أيضا عبر يوتيوب.

نصائح أخرى

منذ فترة ارتكبت pycallgraph الذي يولد تصور من رمز Python الخاص بك. يحرر: لقد قمت بتحديث المثال للعمل مع 3.3، أحدث إصدار اعتبارا من هذه الكتابة.

بعد pip install pycallgraph والتثبيت graphviz. يمكنك تشغيله من سطر الأوامر:

pycallgraph graphviz -- ./mypythonscript.py

أو، يمكنك الملف الشخصي أجزاء معينة من التعليمات البرمجية الخاصة بك:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

أي من هذه سوف تولد pycallgraph.png ملف مشابه للصورة أدناه:

enter image description here

تجدر الإشارة إلى أن استخدام Profiler يعمل فقط (افتراضيا) على الخيط الرئيسي، ولن تحصل على أي معلومات من مؤشرات الترابط الأخرى إذا كنت تستخدمها. هذا يمكن أن يكون قليلا من gotcha لأنها غير مخصبة تماما في وثائق ملفوسة.

إذا كنت ترغب أيضا في تحديد مواضيع الملف الشخصي، فأنت تريد أن ننظر إلى threading.setprofile() وظيفة في المستندات.

يمكنك أيضا إنشاء الخاصة بك threading.Thread Subclass للقيام بذلك:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

واستخدام ذلك ProfiledThread فئة بدلا من المعيار واحد. قد يوفر لك المزيد من المرونة، لكنني لست متأكدا من أنه يستحق كل هذا العناء، خاصة إذا كنت تستخدم رمز الطرف الثالث الذي لن يستخدم فئتك.

تعد Python Wiki صفحة رائعة لموارد التنميط:http://wiki.python.org/moin/pythonspeed/performancetips#profiling_code.

كما هو مستندات Python:http://docs.python.org/library/profile.html.

كما هو موضح بواسطة Chris Lawlor Cprofile هو أداة رائعة ويمكن استخدامها بسهولة للطباعة على الشاشة:

python -m cProfile -s time mine.py <args>

أو لملف:

python -m cProfile -o output.file mine.py <args>

PS> إذا كنت تستخدم Ubuntu، تأكد من تثبيت Python-Profile

sudo apt-get install python-profiler 

إذا قمت بالإخراج إلى الملف، فيمكنك الحصول على تصورات رائعة باستخدام الأدوات التالية

pycallgraph: أداة لإنشاء صور الرسم البياني للمكالمات
ثبيت:

 sudo pip install pycallgraph

يركض:

 pycallgraph mine.py args

رأي:

 gimp pycallgraph.png

يمكنك استخدام ما تريد عرض ملف PNG، استخدمت الأعرج
لسوء الحظ أنا في كثير من الأحيان

نقطة: الرسم البياني كبير جدا بالنسبة لشركة القاهرة العارض. التحجيم بنسبة 0.257079 لتناسب

مما يجعل صوري صغيرة بشكل غير مناسب. لذلك أنا عادة إنشاء ملفات SVG:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

ملاحظة: تأكد من تثبيت Graphviz (الذي يوفر برنامج DOT):

sudo pip install graphviz

الرسوم البيانية البديلة باستخدام gprof2dot عبر maxy / quodlibetor:

sudo pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

@ تعليق ماكسي على هذه الإجابة ساعدني بما فيه الكفاية لأعتقد أنه يستحق إجابته الخاصة: كان لدي بالفعل ملفات .pstats التي تم إنشاؤها cprofile ولم أرغب في إعادة تشغيل الأشياء مع pycallgraph، لذلك اعتدت GPROF2DOT., ، وحصلت svgs جميلة:

$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

وبلام!

يستخدم DOT (نفس الشيء الذي يستخدمه Pycallgraph) حتى يشبه الإخراج مماثلة. أحصل على الانطباع بأن GPROF2DOT يفقد معلومات أقل رغم ذلك:

gprof2dot example output

ركضت إلى أداة مفيدة تسمى snakeviz. عند البحث في هذا الموضوع. Snakeviz هي أداة تصور منشط على الويب. من السهل جدا تثبيت واستخدامها. الطريقة المعتادة التي أستخدمها هي إنشاء ملف إحصائي مع %prun ثم قم بالتحليل في Snakeviz.

تقنية Viz الرئيسية المستخدمة هي غرار الشمس كما هو مبين أدناه، حيث يتم ترتيب التسلسل الهرمي للمكالمات الوظيفة كطبقات من الأقواس ومعلومات الوقت المشفرة في عرضها الزاوي.

أفضل شيء يمكنك التفاعل مع المخطط. على سبيل المثال، للتكبير / التصغير في المرء النقر فوق قوس، وسيتم توسيع القوس ونحيلها كشراعة أمة الله الجديدة لعرض المزيد من التفاصيل.

enter image description here

اعتقد انه cProfile هو عظيم للتنميط، في حين kcachegrind رائع لتصور النتائج. ال pyprof2calltree بين مقابض تحويل الملفات.

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

لتثبيت الأدوات المطلوبة (على Ubuntu، على الأقل):

apt-get install kcachegrind
pip install pyprof2calltree

النتائج:

Screenshot of the result

تجدر الإشارة أيضا إلى عارض تفريغ Gui CProfile runsnakerun.. وبعد يسمح لك بفرز وتحديد، وبالتالي التكبير في الأجزاء ذات الصلة من البرنامج. أحجام المستطيلات في الصورة يتناسب مع الوقت المستغرق. إذا كنت الماوس فوق مستطيل، فهذا يبرز تلك المكالمة في الجدول وفي كل مكان على الخريطة. عند النقر المزدوج فوق المستطيل الذي يقوم به في هذا الجزء. سوف تظهر لك من يدعو هذا الجزء وما يدعو هذا الجزء.

المعلومات الوصفية مفيدة للغاية. إنه يوضح لك رمز هذا البت والتي يمكن أن تكون مفيدة عند التعامل مع مكالمات مكاتب مدمجة. يخبرك أي ملف وما هو السطر للعثور على التعليمات البرمجية.

تريد أيضا أن تشير إلى ذلك، قال المرجع "التنميط"، لكن يبدو أنه يعني "توقيت". ضع في اعتبارك برامج العقل ستشغل أبطأ عند عرضها.

enter image description here

أبسط و أسرع طريقة للعثور على المكان الذي يحدث فيه طوال الوقت.

1. pip install snakeviz

2. python -m cProfile -o temp.dat <PROGRAM>.py

3. snakeviz temp.dat

يرسم مخطط دائري في متصفح. أكبر قطعة هي وظيفة المشكلة. بسيط جدا.

وحدة التنميط لطيفة هي الخط _profiler (يسمى باستخدام البرنامج النصي kernprof.py). يمكن تنزيلها هنا.

فهمي هو أن CProfile يعطي معلومات فقط حول الوقت الإجمالي الذي يقضيه في كل وظيفة. لذلك لا يتم توقيت الخطوط الفردية من التعليمات البرمجية. هذه مشكلة في الحوسبة العلمية لأن خط واحد في كثير من الأحيان يمكن أن يستغرق الكثير من الوقت. أيضا، كما أتذكر، لم يقم CProfile بالقبض على الوقت الذي أقيم فيه Numpy.dot.

pprofile.

line_profiler (قدمت بالفعل هنا) مستوحاة أيضا pprofile, ، الذي يوصف بأنه:

خط الحبيبية، دراسة الخيط الحتمية والإحصائية Pure-Python Profiler

يوفر خط الحبيبية line_profiler, ، هو بيثون نقي، يمكن استخدامه كأمر دائم أو وحدة نمطية، ويمكن حتى إنشاء ملفات تنسيق Callgrind التي يمكن تحليلها بسهولة [k|q]cachegrind.

VProf.

يوجد ايضا VProf., ، حزمة بيثون الموصوفة كما:

...] توفير تصورات غنية وتفاعلية لمختلف خصائص برنامج Python مثل وقت التشغيل واستخدام الذاكرة.

heatmap

أنا خلقت مؤخرا تونة لتصور Python وقت التشغيل واستيراد الملفات الشخصية؛ هذا قد يكون مفيدا هنا.

enter image description here

تثبيت مع

pip3 install tuna

إنشاء ملف تعريف وقت التشغيل

python -mcProfile -o program.prof yourfile.py

أو ملف تعريف الاستيراد (Python 3.7+ مطلوب)

python -X importprofile yourfile.py 2> import.log

ثم فقط تشغيل التونة على الملف

tuna program.prof

هناك الكثير من الإجابات العظيمة ولكنها إما استخدام سطر الأوامر أو بعض البرامج الخارجية لمجموعة التنميط و / أو فرز النتائج.

لقد فاتني حقا بطريقة ما يمكنني استخدامها في IDE (Eclipse-pydev) دون لمس سطر الأوامر أو تثبيت أي شيء. حتى هنا هو عليه.

التنميط دون سطر الأوامر

def count():
    from math import sqrt
    for x in range(10**5):
        sqrt(x)

if __name__ == '__main__':
    import cProfile, pstats
    cProfile.run("count()", "{}.profile".format(__file__))
    s = pstats.Stats("{}.profile".format(__file__))
    s.strip_dirs()
    s.sort_stats("time").print_stats(10)

يرى مستندات أو إجابات أخرى لمزيد من المعلومات.

بعد إجابة جو شو حول رمز متعدد الخيوط لا يعمل كما هو متوقع، احسب أن runcall الطريقة في CProfile هي مجرد القيام self.enable() و self.disable() يدعو حول مكالمة الوظيفة المذهلة، بحيث يمكنك ببساطة أن تفعل ذلك بنفسك ولدي كل الكود الذي تريده بين الحد الأدنى من التداخل مع التعليمات البرمجية الموجودة.

في فيرالال مصدر هناك فئة مفيدة للغاية والديكور التي يمكن أن تجعل التنميط (حتى لطرق / وظائف محددة) سهلة للغاية. يمكن بعد ذلك مشاهدة الناتج بشكل مريح للغاية في KCachegrind.

CProfile رائع للتنميط السريع ولكن معظم الوقت كان ينتهي بالنسبة لي مع الأخطاء. دالة RunCTX يحل هذه المشكلة عن طريق التهيئة بشكل صحيح البيئة والمتغيرات، ونأمل أن تكون مفيدة لشخص ما:

import cProfile
cProfile.runctx('foo()', None, locals())

طريقي هو استخدام yappi (https://code.google.com/p/yappi/). إنه مفيد بشكل خاص جنبا إلى جنب مع خادم RPC حيث (حتى فقط لتصحيح الأخطاء) تقوم بتسجيل الأسلوب للبدء، وإيقاف وطباعة معلومات التنميط، على سبيل المثال بهذه الطريقة:

@staticmethod
def startProfiler():
    yappi.start()

@staticmethod
def stopProfiler():
    yappi.stop()

@staticmethod
def printProfiler():
    stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
    statPrint = '\n'
    namesArr = [len(str(stat[0])) for stat in stats.func_stats]
    log.debug("namesArr %s", str(namesArr))
    maxNameLen = max(namesArr)
    log.debug("maxNameLen: %s", maxNameLen)

    for stat in stats.func_stats:
        nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
        log.debug('nameAppendSpaces: %s', nameAppendSpaces)
        blankSpace = ''
        for space in nameAppendSpaces:
            blankSpace += space

        log.debug("adding spaces: %s", len(nameAppendSpaces))
        statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
            round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"

    log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
    log.log(1000, statPrint)

ثم عندما يعمل البرنامج الخاص بك، يمكنك أن تبدأ Profiler في أي وقت عن طريق الاتصال startProfiler طريقة RPC وتفريغ معلومات التنميط إلى ملف السجل عن طريق الاتصال printProfiler (أو تعديل طريقة RPC لإرجاعها إلى المتصل) والحصول على مثل هذا الإخراج:

2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
name                                                                                                                                      ncall     ttot    tsub
2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
<string>.__new__:8                                                                                                                        220       0.0     0.0
C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
<string>.__new__:8                                                                                                                        4         0.0     0.0
C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 

قد لا تكون مفيدة للغاية بالنسبة لبرامج النصوص القصيرة ولكنها تساعد على تحسين عمليات نوع الخادم خاصة بالنظر إلى printProfiler يمكن استدعاء الطريقة عدة مرات مع مرور الوقت لملف التعريف ومقارنة سيناريوهات استخدام البرنامج المختلفة.

هل تريد أن تعرف ماذا بحق الجحيم الذي يفعله بيثون؟ أدخل تفتيش قذيفة. يتيح لك تفقد Shell طباعة / تغيير Globals وتشغيل الوظائف دون مقاطعة البرنامج النصي قيد التشغيل. الآن مع تاريخ الطلب التلقائي والأمر (فقط على Linux).

فحص قذيفة ليس مصححا على غرار PDB.

https://github.com/amoffat/inspect-shell.

يمكنك استخدام ذلك (ولقد اليد الخاص بك).

لإضافة إلى https://stackoverflow.com/a/582337/1070617.,

كتبت هذه الوحدة التي تسمح لك باستخدام CProfile وعرض إخراجها بسهولة. المزيد هنا: https://github.com/ymichael/cprofilev.

$ python -m cprofilev /your/python/program
# Go to http://localhost:4000 to view collected statistics.

انظر أيضا: http://ymichael.com/2017/03/08/Profiling-phoThon-With-cprofile.html. حول كيفية فهم الإحصاءات التي تم جمعها.

أداة جديدة للتعامل مع التنميط في Python هي Pyvmmonitor: http://www.pyvmmonitor.com/

لديها بعض الميزات الفريدة مثل

  • إرفاق profiler إلى برنامج تشغيل (CPYTHON)
  • عند الطلب على التنميط مع تكامل Yappi
  • الملف الشخصي على جهاز مختلف
  • دعم العمليات المتعددة (متعدد المعالجات، Django ...)
  • عرض أخذ العينات / وحدة المعالجة المركزية العيش (مع اختيار النطاق الزمني)
  • تحديد التنميط من خلال تكامل CProfile / الملف الشخصي
  • تحليل النتائج PSTats الحالية
  • فتح ملفات dot.
  • وصول API البرنامجي
  • عينات المجموعة حسب الطريقة أو الخط
  • التكامل pydev
  • التكامل بايشرم

ملاحظة: إنها تجارية، ولكن مجانا للمصدر المفتوح.

سيعتمد على ما تريد رؤيته من التنميط. يمكن إعطاء مقاييس وقت بسيط بواسطة (bash).

time python python_prog.py

حتى "/ USR / BIN / TIME" يمكن إخراج مقاييس مفصلة باستخدام علامة "-verبوز".

لفحص مقاييس الوقت المقدم من كل وظيفة وفهم أفضل مدى إنفاق مقدار الوقت على الوظائف، يمكنك استخدام CProfile Inbuilt في Python.

الذهاب إلى مقاييس أكثر تفصيلا مثل الأداء، والوقت ليس متريا الوحيد. يمكنك القلق بشأن الذاكرة، المواضيع الخ
خيارات التنميط:
1. line_profiler. هو ملف تعريف آخر يستخدم عادة لمعرفة خط تقسيط توقيت.
2. memory_profiler. هي أداة لاستخدام ذاكرة الملف الشخصي.
3. هاب (من مشروع GUPPY) الملف الشخصي كيف يتم استخدام الكائنات في كومة الكومة.

هذه هي بعض من تلك المشتركة التي أميل إلى استخدامها. ولكن إذا كنت ترغب في معرفة المزيد، حاول قراءة هذا كتابإنه كتاب جيد جدا بدءا من الأداء في الاعتبار. يمكنك الانتقال إلى موضوعات متقدمة على استخدام Python Cython and Jit (فقط في الوقت المناسب).

هناك أيضا ملتذلا إحصائيا يسمى statprof. وبعد إنه ملف تعريف أخذ العينات، لذلك يضيف الحد الأدنى من النفقات العامة إلى التعليمات البرمجية الخاصة بك ويعطي توقيت القائم على الخط (وليس فقط). إنها أكثر ملاءمة للتطبيقات في الوقت الفعلي الناعم مثل الألعاب، ولكن قد يكون لها دقة أقل من CProfile.

ال نسخة في pypi. قديم قليلا، لذلك يمكن تثبيته pip عن طريق تحديد مستودع جيت:

pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

يمكنك تشغيله مثل هذا:

import statprof

with statprof.profile():
    my_questionable_function()

أنظر أيضا https://stackoverflow.com/a/10333592/320036.

عندما لا أكون جذر على الخادم، أستخدمlsprofcalltree.py. وتشغيل برنامجي مثل هذا:

python lsprofcalltree.py -o callgrind.1 test.py

ثم يمكنني فتح التقرير مع أي برنامج متوافق مع Callgrind، مثل qcachegrind.

GPROF2DOT_MAGIC.

وظيفة السحر ل gprof2dot إلى ملف التعريف أي بيان Python كشركة بياني نقطة في دفتر Jupyterlab أو Jupyter.

enter image description here

جيثب ريبو: https://github.com/mattijn/gprof2d_magic.

تثبيت

تأكد من أنك حزمة Python gprof2dot_magic.

pip install gprof2dot_magic

تبعياتها gprof2dot و graphviz سيتم تثبيت كذلك

الاستعمال

لتمكين الوظيفة السحرية، قم أولا بالتحميل gprof2dot_magic وحدة

%load_ext gprof2dot_magic

ثم ملف تعريف أي عبارة خط كشركة بياني نقطة على هذا النحو:

%gprof2dot print('hello world')

enter image description here

الحل الطرفي فقط (وأبسط) إذا فشل كل هؤلاء الذين يتوهمون واجهة المستخدم في تثبيت أو تشغيل:
يتجاهل cProfile تماما واستبدالها pyinstrument, من شأنها جمع وعرض شجرة المكالمات مباشرة بعد التنفيذ.

ثبت:

$ pip install pyinstrument

الملف الشخصي وعرض النتيجة:

$ python -m pyinstrument ./prog.py

يعمل مع Python2 و 3.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top