خانه / آموزش‌ها / آموزش پروفایلینگ و بهینه‌سازی کد در پایتون

آموزش پروفایلینگ و بهینه‌سازی کد در پایتون

🐍 HomeOfPython
|
📅 1404/10/24

سطح مقدماتی (Beginner Level)

پروفایلینگ (Profiling) به معنای تحلیل برنامه برای اندازه‌گیری پارامترهایی مثل زمان اجرا (Execution Time) یا میزان مصرف حافظه است. در سطح مقدماتی، یاد می‌گیریم چگونه زمان اجرای تکه‌های کوچک کد را اندازه بگیریم.

۱. اندازه‌گیری ساده با time

ساده‌ترین روش، ثبت زمان شروع و پایان یک عملیات است. برای این کار بهتر است از time.perf_counter() استفاده کنید که دقت بالاتری نسبت به time.time() دارد.

مثال ۱: اندازه‌گیری زمان اجرای یک حلقه ساده.

Python

مثال ۲: مقایسه زمان اجرای دو تابع ساده (لیست معمولی vs لیست کامپریهنشن).

Python

۲. استفاده از ماژول timeit

برای اندازه‌گیری دقیق تکه کدهای کوچک (Micro-benchmarking)، روش دستی بالا خطا دارد (به دلیل سربار سیستم عامل). ماژول استاندارد timeit این کار را با اجراهای متعدد انجام می‌دهد تا میانگین دقیق‌تری ارائه دهد.

مثال ۱: استفاده از timeit برای تست سرعت الحاق رشته‌ها.

Python

مثال ۲: استفاده از timeit.repeat برای اطمینان بیشتر. این متد چندین بار تست را تکرار می‌کند تا کمترین زمان (Best Case) را پیدا کنید.

python
import timeit

setup_code = "from math import sqrt"
stmt_code = "sqrt(12345)"

# ۵ بار تکرار می‌کند، هر بار ۱۰،۰۰۰ اجرا
results = timeit.repeat(stmt=stmt_code, setup=setup_code, repeat=5, number=10000)

print(f"All runs: {results}")
print(f"Best time: {min(results)}")

سطح پیشرفته (Professional Level)

در برنامه‌های بزرگ، اندازه‌گیری دستی توابع کارآمد نیست. ما نیاز داریم بدانیم کدام تابع بیشترین زمان را مصرف می‌کند (گلوگاه یا Bottleneck کجاست). برای این کار از Deterministic Profiling با ماژول cProfile استفاده می‌کنیم.

۱. تحلیل جامع با cProfile

این ماژول تعداد فراخوانی‌ها (ncalls)، زمان خالص تابع (tottime) و زمان تجمعی (cumtime) را گزارش می‌دهد.

مثال ۱: پروفایل کردن یک اسکریپت کامل درون کد.

Python

مثال ۲: ذخیره خروجی پروفایل در فایل (برای نمایش با ابزارهای گرافیکی مثل SnakeViz).

python
import cProfile

def heavy_computation():
    return [x**2 for x in range(100000)]

# نتیجه را در فایل stats.prof ذخیره می‌کند
cProfile.run('heavy_computation()', 'stats.prof')
print("Profile data saved to stats.prof")

۲. تحلیل نتایج با pstats

خروجی cProfile به صورت متنی ممکن است شلوغ باشد. با کلاس pstats می‌توانیم نتایج را مرتب و فیلتر کنیم.

مثال ۱: مرتب‌سازی بر اساس زمان تجمعی (Cumulative Time). این روش نشان می‌دهد کدام تابع (و زیرمجموعه‌هایش) بیشترین زمان برنامه را گرفته‌اند.

Python

۳. ساخت دکوریتور پروفایلینگ (Profiling Decorator)

یک روش حرفه‌ای برای دیباگ پرفرمنس، ساختن دکوریتوری است که فقط تابع مورد نظر را پروفایل کند.

مثال ۱: دکوریتور سفارشی با cProfile.

Python

۴. نکات بهینه‌سازی (Optimization Tips)

بعد از پیدا کردن گلوگاه با پروفایلینگ، باید کد را بهینه کنید.

  • نکته ۱: دسترسی به متغیرهای Local سریع‌تر از Global است.
  • نکته ۲: استفاده از توابع Built-in (مثل map یا sum) معمولاً سریع‌تر از حلقه‌های پایتونی است چون در C پیاده‌سازی شده‌اند.

مثال: تاثیر استفاده از متغیر لوکال در حلقه.

Python