بهینه سازی کد پایتون با استفاده از cProfile و ماژول PyPy: یک راهنمای کامل

مقدمه
بهعنوان توسعهدهندگان پایتون، قبل از اینکه نگران بهینهسازی کد خود باشیم، اغلب بر روی کارکردن کد خود تمرکز میکنیم. با این حال، هنگامی که با برنامه های کاربردی در مقیاس بزرگ یا کدهای عملکرد حیاتی سروکار دارید، بهینه سازی بسیار مهم می شود. در این پست، دو ابزار قدرتمندی را که میتوانید برای بهینهسازی کد پایتون خود استفاده کنید، پوشش خواهیم داد: cProfile
ماژول و مفسر PyPy.
در پایان این پست، یاد خواهید گرفت:
- نحوه شناسایی تنگناهای عملکرد با استفاده از
cProfile
ماژول - چگونه کد خود را برای سرعت بهینه کنیم
- نحوه استفاده از PyPy برای تسریع بیشتر برنامه های پایتون با کامپایل Just-in-Time (JIT).
چرا بهینه سازی عملکرد مهم است
پایتون به دلیل سهولت استفاده، خوانایی و اکوسیستم وسیع کتابخانهها شناخته شده است. اما همچنین به دلیل ماهیت تفسیری آن نسبت به برخی از زبان های دیگر مانند C یا جاوا کندتر است. بنابراین، دانستن نحوه بهینهسازی کد پایتون میتواند در برنامههای حساس به عملکرد، مانند مدلهای یادگیری ماشین، سیستمهای بلادرنگ یا سیستمهای معاملاتی با فرکانس بالا، حیاتی باشد.
بهینه سازی معمولاً این مراحل را دنبال می کند:
- کد خود را نمایه کنید تا بفهمیم تنگناها کجاست
- کد را بهینه کنید در زمینه هایی که ناکارآمد هستند.
- کد بهینه شده را اجرا کنید در یک مفسر سریعتر، مانند PyPy، برای دستیابی به حداکثر کارایی.
حالا بیایید با پروفایل کد شما شروع کنیم.
مرحله 1: پروفایل کد خود را با cProfile
چیست cProfile
?
cProfile
یک ماژول داخلی پایتون برای پروفایل عملکرد است. این برنامه زمان اجرای هر تابع در کد شما را ردیابی میکند که میتواند به شما در شناسایی توابع یا بخشهایی از کد که باعث کاهش سرعت میشوند کمک کند.
با استفاده از cProfile
از خط فرمان
ساده ترین راه برای ایجاد نمایه یک اسکریپت اجرای آن است cProfile
از خط فرمان به عنوان مثال، فرض کنید یک اسکریپت به نام دارید my_script.py
:
python -m cProfile -s cumulative my_script.py
توضیح:
-
-m cProfile
: اجرا می کندcProfile
ماژول به عنوان بخشی از کتابخانه استاندارد پایتون. -
-s cumulative
: نتایج پروفایل را بر اساس زمان تجمعی صرف شده در هر تابع مرتب می کند. -
my_script.py
: اسکریپت پایتون شما.
این یک تفکیک دقیق از جایی که کد شما زمان خود را صرف می کند ایجاد می کند.
مثال: پروفایل یک اسکریپت پایتون
بیایید به یک اسکریپت پایه پایتون نگاه کنیم که اعداد فیبوناچی را به صورت بازگشتی محاسبه می کند:
def fibonacci(n):
if n 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
if __name__ == "__main__":
print(fibonacci(30))
اجرای این اسکریپت با cProfile
:
python -m cProfile -s cumulative fibonacci_script.py
درک کردن cProfile
خروجی
یک بار که می دوید cProfile
، چیزی شبیه به این را خواهید دید:
ncalls tottime percall cumtime percall filename:lineno(function)
8320 0.050 0.000 0.124 0.000 fibonacci_script.py:3(fibonacci)
هر ستون داده های کلیدی عملکرد را ارائه می دهد:
- تماس می گیرد: تعداد دفعاتی که تابع فراخوانی شده است.
- تایم: کل زمان صرف شده در تابع (به استثنای توابع فرعی).
- cumtime: زمان تجمعی صرف شده در تابع (از جمله توابع فرعی).
- صدا زدن: زمان هر تماس
اگر شما fibonacci
عملکرد زمان زیادی می برد، این خروجی به شما نشان می دهد که تلاش های بهینه سازی خود را کجا متمرکز کنید.
نمایه سازی بخش های خاص کد شما
همچنین می توانید استفاده کنید cProfile
اگر فقط میخواهید بخشهای خاصی را نمایه کنید، به صورت برنامهنویسی در کد خود قرار دهید.
import cProfile
def fibonacci(n):
if n 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
if __name__ == "__main__":
cProfile.run('fibonacci(30)')
مرحله 2: بهینه سازی کد پایتون
هنگامی که با استفاده از گلوگاه های کد خود را شناسایی کردید cProfile
، زمان بهینه سازی فرا رسیده است.
تکنیک های رایج بهینه سازی پایتون
-
از توابع داخلی استفاده کنید: توابع داخلی مانند
sum()
،min()
، وmax()
در پایتون بسیار بهینه شده اند و معمولا سریعتر از حلقه های پیاده سازی دستی هستند.
مثال:
# Before: Custom sum loop
total = 0
for i in range(1000000):
total += i
# After: Using built-in sum
total = sum(range(1000000))
- از تماس های کاربردی غیر ضروری خودداری کنید: فراخوانی های تابع دارای سربار هستند، به خصوص حلقه های داخلی. سعی کنید تماس های اضافی را کاهش دهید.
مثال:
# Before: Unnecessary repeated calculations
for i in range(1000):
print(len(my_list)) # len() is called 1000 times
# After: Compute once and reuse
list_len = len(my_list)
for i in range(1000):
print(list_len)
- حفظ کردن: برای توابع بازگشتی، می توانید از حافظه گذاری برای ذخیره نتایج محاسبات گران قیمت استفاده کنید تا از تکرار کار جلوگیری کنید.
مثال:
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
این امر با ذخیره کردن نتایج هر تماس بازگشتی، محاسبه فیبوناچی را تا حد زیادی سرعت می بخشد.
مرحله 3: استفاده از PyPy برای کامپایل سازی به موقع
PyPy چیست؟
PyPy یک مفسر جایگزین پایتون است که از کامپایل Just-in-Time (JIT) برای سرعت بخشیدن به کد پایتون شما استفاده می کند. PyPy مسیرهای کد اغلب اجرا شده را در کد ماشین کامپایل می کند و آن را بسیار سریعتر از مفسر استاندارد CPython برای کارهای خاص می کند.
در حال نصب PyPy
می توانید PyPy را با استفاده از یک مدیریت بسته مانند نصب کنید apt
در لینوکس یا brew
در macOS:
# On Ubuntu
sudo apt-get install pypy3
# On macOS (using Homebrew)
brew install pypy3
اجرای کد پایتون با PyPy
هنگامی که PyPy نصب شد، می توانید اسکریپت خود را به جای CPython با آن اجرا کنید:
pypy3 my_script.py
چرا از PyPy استفاده کنیم؟
- PyPy ایده آل برای وظایف محدود به CPU جایی که برنامه بیشتر زمان خود را در محاسبات صرف می کند (به عنوان مثال، حلقه ها، توابع بازگشتی، اعداد خرد کردن).
- کامپایلر JIT PyPy مسیرهای کدی که اغلب اجرا می شوند را بهینه می کند، که می تواند منجر به افزایش سرعت قابل توجه بدون تغییر کد شود.
مرحله 4: ترکیب کردن cProfile
و PyPy برای حداکثر بهینه سازی
اکنون بیایید این ابزارها را برای بهینه سازی کامل کد پایتون خود ترکیب کنیم.
نمونه گردش کار
-
کد خود را نمایه کنید با استفاده از
cProfile
برای شناسایی تنگناها - کد خود را بهینه کنید با استفاده از تکنیکهایی که در مورد آن بحث کردیم (توکار، حافظهگذاری، اجتناب از فراخوانیهای غیرضروری توابع).
- کد بهینه شده خود را اجرا کنید با PyPy برای دستیابی به بهبود عملکرد بیشتر.
بیایید مثال فیبوناچی خود را دوباره مرور کنیم و همه چیز را کنار هم بگذاریم.
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
if __name__ == "__main__":
import cProfile
cProfile.run('print(fibonacci(30))')
پس از بهینه سازی کد با حافظه، آن را با استفاده از PyPy برای بهبود عملکرد بیشتر اجرا کنید:
pypy3 fibonacci_script.py
نتیجه گیری
با اعمال اهرم cProfile
و PyPy، می توانید کد پایتون خود را تا حد زیادی بهینه کنید. استفاده کنید cProfile
برای شناسایی و رفع تنگناهای عملکرد در کد خود. سپس، از PyPy برای افزایش بیشتر سرعت اجرای برنامه خود از طریق کامپایل JIT استفاده کنید.
به طور خلاصه:
- کد خود را با
cProfile
برای درک تنگناهای عملکرد - از تکنیکهای بهینهسازی پایتون، مانند استفاده از داخلیها و حافظهسازی استفاده کنید.
- برای دستیابی به عملکرد بهتر، کد بهینه شده را روی PyPy اجرا کنید.
با این رویکرد، میتوانید برنامههای پایتون خود را سریعتر و کارآمدتر اجرا کنید، مخصوصاً برای کارهای محدود به CPU.
با من ارتباط برقرار کنید:
Github
لینکدین