profile --- Pure Python profiler¶
Source code: Lib/profile.py
منسوخ شده از نسخهی 3.15, در نسخهی 3.17 حذف خواهد شد.
The profile module is deprecated and will be removed in Python 3.17.
Use profiling.tracing instead.
The profile module provides a pure Python implementation of a
deterministic profiler. While useful for understanding profiler internals or
extending profiler behavior through subclassing, its pure Python implementation
introduces significant overhead compared to the C-based profiling.tracing
module.
For most profiling tasks, use:
profiling.samplingfor production debugging with zero overheadprofiling.tracingfor development and testing
Migration¶
Migrating from profile to profiling.tracing is straightforward.
The APIs are compatible:
# Old (deprecated)
import profile
profile.run('my_function()')
# New (recommended)
import profiling.tracing
profiling.tracing.run('my_function()')
For most code, replacing import profile with import profiling.tracing
(and using profiling.tracing instead of profile throughout) provides
a straightforward migration path.
توجه
The cProfile module remains available as a backward-compatible alias
to profiling.tracing. Existing code using import cProfile will
continue to work without modification.
profile and profiling.tracing module reference¶
Both the profile and profiling.tracing modules provide the
following functions:
- profile.run(command, filename=None, sort=-1)¶
این تابع یک آرگومان واحد را که میتوان آن را به تابع
exec()ارسال کرد، و یک نام پرونده اختیاری میپذیرد. در همه موارد، این روال کد زیر را اجرا میکند:exec(command, __main__.__dict__, __main__.__dict__)
و آمار پروفایلسازی را از اجرا جمعآوری میکند. اگر نام پروندهای وجود نداشته باشد، این تابع بهطور خودکار یک نمونه از
Statsایجاد میکند و یک گزارش پروفایلسازی ساده چاپ میکند. اگر مقدار مرتبسازی مشخصشده باشد، به این نمونه ازStatsداده میشود تا نحوهی مرتبسازی نتایج را کنترل کند.
- profile.runctx(command, globals, locals, filename=None, sort=-1)¶
این تابع مشابه
run()است، با آرگومانهای اضافهای برای فراهمکردن نگاشتهای globals و locals برای رشتهی command. این روال اجرا میکند:exec(command, globals, locals)
و آمارهای پروفایلگیری را همانطور که در تابع
run()بالا آمده است، جمعآوری میکند.
- class profile.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)¶
This class is normally only used if more precise control over profiling is needed than what the
profiling.tracing.run()function provides.میتوان از طریق آرگومان timer، یک زمانسنج سفارشی برای اندازهگیری مدتزمان اجرای کد فراهم کرد. این باید تابعی باشد که یک عدد واحد را برمیگرداند و نشاندهندهی زمان جاری است. اگر این عدد یک عدد صحیح باشد، timeunit ضریبی را مشخص میکند که مدتزمان هر واحد زمان را تعیین میکند. برای مثال، اگر زمانسنج زمانهایی را برگرداند که بر حسب هزاران ثانیه اندازهگیری شدهاند، واحد زمان
.001خواهد بود.استفاده مستقیم از کلاس
Profileامکان قالببندی نتایج پروفایل را بدون نوشتن دادههای پروفایل در یک پرونده فراهم میکند:import profiling.tracing import pstats import io from pstats import SortKey pr = profiling.tracing.Profile() pr.enable() # ... do something ... pr.disable() s = io.StringIO() sortby = SortKey.CUMULATIVE ps = pstats.Stats(pr, stream=s).sort_stats(sortby) ps.print_stats() print(s.getvalue())
The
Profileclass can also be used as a context manager (supported only inprofiling.tracing, not in the deprecatedprofilemodule; see انواع مدیر زمینه):import profiling.tracing with profiling.tracing.Profile() as pr: # ... do something ... pr.print_stats()
تغییر یافته در نسخهی 3.8: پشتیبانی از مدیر زمینه افزوده شد.
- enable()¶
Start collecting profiling data. Only in
profiling.tracing.
- disable()¶
Stop collecting profiling data. Only in
profiling.tracing.
- create_stats()¶
جمعآوری دادههای پروفایلگیری را متوقف کنید و نتایج را بهصورت داخلی بهعنوان پروفایل فعلی ثبت کنید.
- print_stats(sort=-1)¶
یک شیء
Statsبر اساس پروفایل فعلی ایجاد کنید و نتایج را در stdout چاپ کنید.The sort parameter specifies the sorting order of the displayed statistics. It accepts a single key or a tuple of keys to enable multi-level sorting, as in
pstats.Stats.sort_stats().اضافه شده در نسخهی 3.13:
print_stats()اکنون یک تاپل از کلیدها را میپذیرد.
- dump_stats(filename)¶
نتایج پروفایل فعلی را در filename بنویسید.
- runcall(func, /, *args, **kwargs)¶
func(*args, **kwargs)را پروفایل میکند
توجه داشته باشید که پروفایلگیری تنها در صورتی کار میکند که فرمان/تابع فراخوانیشده واقعاً بازگشت داشته باشد. اگر مفسر خاتمه یابد (مثلاً از طریق فراخوانی sys.exit() در حین اجرای فرمان/تابع فراخوانیشده)، هیچ نتیجهای از پروفایلگیری چاپ نخواهد شد.
Differences from profiling.tracing¶
The profile module differs from profiling.tracing in several
ways:
Higher overhead. The pure Python implementation is significantly slower than the C implementation, making it unsuitable for profiling long-running programs or performance-sensitive code.
Calibration support. The profile module supports calibration to
compensate for profiling overhead. This is not needed in profiling.tracing
because the C implementation has negligible overhead.
Custom timers. Both modules support custom timers, but profile
accepts timer functions that return tuples (like os.times()), while
profiling.tracing requires a function returning a single number.
Subclassing. The pure Python implementation is easier to subclass and extend for custom profiling behavior.
What is deterministic profiling?¶
Deterministic profiling is meant to reflect the fact that all function
call, function return, and exception events are monitored, and precise
timings are made for the intervals between these events (during which time the
user's code is executing). In contrast, statistical profiling (which is
provided by the profiling.sampling module) periodically samples the
effective instruction pointer, and deduces where time is being spent. The
latter technique traditionally involves less overhead (as the code does not
need to be instrumented), but provides only relative indications of where time
is being spent.
در پایتون، از آنجا که در حین اجرا یک مفسر فعال است، برای انجام پروفایلگیری قطعی (deterministic profiling) نیازی به وجود کد ابزاربندیشده (instrumented code) نیست. پایتون بهطور خودکار یک hook (کالبک اختیاری) برای هر رویداد فراهم میکند. علاوه بر این، ماهیت تفسیری پایتون معمولاً آنقدر سربار زیادی به اجرا اضافه میکند، بهطوری که پروفایلگیری قطعی معمولاً فقط سربار پردازشی اندکی در برنامههای کاربردی معمولی اضافه میکند. نتیجه این است که پروفایلگیری قطعی چندان پرهزینه نیست، اما آمار گستردهای از زمان اجرا درباره اجرای یک برنامه پایتون ارائه میدهد.
میتوان از آمار تعداد فراخوانیها برای شناسایی اشکالهای کد (تعداد فراخوانیهای غیرمنتظره) و برای شناسایی نقاط ممکن برای بسط درونخطی (inline-expansion) (تعداد فراخوانیهای بالا) استفاده کرد. میتوان از آمار زمان داخلی برای شناسایی «حلقههای داغ» که باید با دقت بهینهسازی شوند، استفاده کرد. باید از آمار زمان تجمعی برای شناسایی خطاهای سطح بالا در انتخاب الگوریتمها استفاده شود. توجه داشته باشید که مدیریت غیرمعمول زمانهای تجمعی در این پروفایلگیر به شما امکان میدهد آمار پیادهسازیهای بازگشتی الگوریتمها را بهطور مستقیم با پیادهسازیهای تکراری مقایسه کنید.
محدودیتها¶
یکی از محدودیتها به دقت اطلاعات زمانبندی مربوط میشود. در پروفایلگیرهای قطعی (deterministic profilers) مشکلی بنیادین در مورد دقت وجود دارد. واضحترین محدودیت این است که «ساعت» زیربنایی تنها با نرخی (معمولاً) حدود ۰٫۰۰۱ ثانیه تیک میزند. بنابراین، هیچ اندازهگیریای دقیقتر از ساعت زیربنایی نخواهد بود. اگر تعداد کافی اندازهگیری انجام شود، «خطا» تمایل دارد بهطور میانگین خنثی شود. متأسفانه، حذف این خطای نخست، منبع دوم خطا را به وجود میآورد.
دومین مشکل این است که از لحظهای که یک رویداد ارسال میشود تا زمانی که فراخوانی پروفایلگیر برای گرفتن زمان واقعاً وضعیت ساعت را دریافت میکند، «مدتی طول میکشد». بهطور مشابه، هنگام خروج از هندلر رویداد پروفایلگیر، از زمانی که مقدار ساعت گرفته شده (و سپس ذخیره شده است) تا زمانی که کد کاربر دوباره در حال اجرا است، تأخیر مشخصی وجود دارد. در نتیجه، توابعی که بارها فراخوانی میشوند یا توابع زیادی را فراخوانی میکنند، معمولاً این خطا را انباشته میکنند. خطایی که به این شکل انباشته میشود، معمولاً کمتر از دقت ساعت است (کمتر از یک تیک ساعت)، اما میتواند انباشته شود و بسیار قابلتوجه شود.
The problem is more important with the deprecated profile module than
with the lower-overhead profiling.tracing. For this reason,
profile provides a means of calibrating itself for a given platform so
that this error can be probabilistically (on the average) removed. After the
profiler is calibrated, it will be more accurate (in a least square sense), but
it will sometimes produce negative numbers (when call counts are exceptionally
low, and the gods of probability work against you :-). ) Do not be alarmed
by negative numbers in the profile. They should only appear if you have
calibrated your profiler, and the results are actually better than without
calibration.
کالیبراسیون¶
The profiler of the profile module subtracts a constant from each event
handling time to compensate for the overhead of calling the time function, and
socking away the results. By default, the constant is 0. The following
procedure can be used to obtain a better constant for a given platform (see
محدودیتها).
import profile
pr = profile.Profile()
for i in range(5):
print(pr.calibrate(10000))
این متد تعداد فراخوانیهای پایتون مشخصشده توسط آرگومان را یک بار بهطور مستقیم و بار دیگر تحت پروفایلگیر اجرا میکند و زمان هر دو را اندازهگیری میکند. سپس سربار پنهان بهازای هر رویداد پروفایلگیر را محاسبه میکند و آن را بهعنوان یک عدد اعشاری بازمیگرداند. برای مثال، روی یک Intel Core i5 با فرکانس ۱٫۸ گیگاهرتز که macOS را اجرا میکند و با استفاده از time.process_time() پایتون بهعنوان زمانسنج، عدد جادویی حدود ۴٫۰۴e-۶ است.
هدف از این تمرین، دستیابی به نتیجهای نسبتاً پایدار است. اگر رایانهی شما بسیار سریع است، یا تابع زمانسنج شما دقت زمانی پایینی دارد، ممکن است لازم باشد ۱۰۰۰۰۰، یا حتی ۱۰۰۰۰۰۰، را پاس بدهید تا نتایج پایداری بگیرید.
هنگامی که پاسخ سازگاری دارید، ۳ روش برای استفاده از آن وجود دارد:
import profile
# 1. Apply computed bias to all Profile instances created hereafter.
profile.Profile.bias = your_computed_bias
# 2. Apply computed bias to a specific Profile instance.
pr = profile.Profile()
pr.bias = your_computed_bias
# 3. Specify computed bias in instance constructor.
pr = profile.Profile(bias=your_computed_bias)
اگر حق انتخاب دارید، بهتر است ثابت کوچکتری را انتخاب کنید، و در این صورت نتایج شما «کمتر» بهصورت منفی در آمار پروفایل نمایش داده میشوند.
استفاده از زمانسنج سفارشی¶
اگر میخواهید نحوه تعیین زمان جاری را تغییر دهید (برای مثال، برای اجبار به استفاده از زمان دیواری یا زمان سپریشده فرایند)، تابع زمانسنجی مورد نظر خود را به سازنده کلاس Profile ارسال کنید:
pr = profile.Profile(your_time_func)
The resulting profiler will then call your_time_func. Depending on whether
you are using profile.Profile or profiling.tracing.Profile,
your_time_func's return value will be interpreted differently:
profile.Profileyour_time_funcباید یک عدد زمانی واحد، یا فهرستی از اعداد را برگرداند که مجموع آنها زمان جاری است (مانند آنچهos.times()برمیگرداند). اگر تابع یک عدد زمانی واحد برگرداند، یا فهرست اعداد برگرداندهشده طول ۲ داشته باشد، نسخهای بهویژه سریع از روال اعزام (dispatch routine) دریافت خواهید کرد.توجه داشته باشید که باید کلاس پروفایلگیر را برای تابع زمانسنجی که انتخاب میکنید کالیبره کنید (به کالیبراسیون مراجعه کنید). در بیشتر ماشینها، زمانسنجی که تنها یک مقدار عدد صحیح برمیگرداند، بهترین نتایج را از نظر سربار کم در حین پروفایلکردن فراهم میکند. (
os.times()نسبتاً بد است، زیرا یک تاپل از مقادیر ممیز شناور برمیگرداند). اگر میخواهید یک زمانسنج بهتر را به تمیزترین روش جایگزین کنید، یک کلاس مشتق کنید و یک متد اعزام (dispatch) جایگزین را که فراخوانی زمانسنج شما را به بهترین شکل مدیریت میکند، بههمراه ثابت کالیبراسیون مناسب، بهصورت سختکد (hardwire) پیادهسازی کنید.profiling.tracing.Profileyour_time_funcباید یک عدد واحد برگرداند. اگر این تابع اعداد صحیح برگرداند، همچنین میتوانید سازندهی کلاس را با یک آرگومان دوم برای مشخص کردن مدتزمان واقعی یک واحد زمان فراخوانی کنید. برای مثال، اگرyour_integer_time_funcمقادیر زمانی را برگرداند که بر حسب هزاران ثانیه اندازهگیری شدهاند، باید نمونهیProfileرا بهصورت زیر بسازید:pr = profiling.tracing.Profile(your_integer_time_func, 0.001)
As the
profiling.tracing.Profileclass cannot be calibrated, custom timer functions should be used with care and should be as fast as possible. For the best results with a custom timer, it might be necessary to hard-code it in the C source of the internal_lsprofmodule.
پایتون 3.3 چندین تابع جدید به time اضافه میکند که میتوان از آنها برای اندازهگیریهای دقیق زمان فرایند یا زمان دیواری استفاده کرد. برای مثال، time.perf_counter() را ببینید.
همچنین ملاحظه نمائید
profilingOverview of Python profiling tools.
profiling.tracingRecommended replacement for this module.
pstatsStatistical analysis and formatting for profile data.