خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

چگونه نمایه مصرف حافظه کد پایتون خود را پیدا کنید

از این نکات برای تجزیه و تحلیل کد خود استفاده کنید و کشف کنید که کجا بیشترین یا کمترین کارایی را دارد.

از آنجایی که “بیش از یک راه برای انجام آن وجود دارد” در پایتون، یافتن کارآمدترین رویکرد حافظه برای برخی کارها می تواند چالش برانگیز باشد. اینجاست که یک نمایه کننده حافظه می تواند کمک کند. علاوه بر ردیابی نشت، تخمین نمایه حافظه کد شما به تعیین اینکه کدام کد از نظر حافظه کارآمد است کمک می کند.

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

چند ابزار برای تخمین نمایه حافظه در پایتون

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

بسیاری از کتابخانه های پروفایل در پایتون وجود دارد. برخی از محبوب ترین آنها memory_profiler، psutil، Tracemalloc و pympler هستند. در این آموزش از memory_profiler و psutil استفاده شده است.

در حالی که psutil برای تخمین مصرف کل حافظه یک روش یا اجرای عملکرد ایده‌آل است، memory_profiler اطلاعات دقیق‌تری درباره استفاده از حافظه، از جمله روندهای استفاده خط به‌واسطه و سطح عملکردی در طول زمان ارائه می‌دهد.

برای شروع، memory_profiler را در محیط مجازی پایتون خود نصب کنید. این نیز psutil را نصب می کند.

pip install memory_profiler

اندازه یک شی را در حافظه بدست آورید

شما می توانید پروفایل حافظه خود را با محاسبه اندازه شیئی که قصد دارید در حافظه استفاده کنید شروع کنید.

این نوع نمایه سازی در ابتدای توسعه مفید است – در حالی که تلاش می شود تا مشخص شود از کدام نوع شی در یک برنامه استفاده شود.

مطلب مرتبط:   نحوه مدیریت واکشی داده در React.js با استفاده از Tanstack Query

به عنوان مثال، اگر در تصمیم گیری برای دستیابی به یک کار، مثلاً نوع داده مناسب پایتون، از کدام روش ها گیر کرده اید، می توانید اندازه هر کدام را بر حسب بایت دریافت کنید تا مشخص کنید کدام روش برای مورد استفاده شما سبک تر است.

روش داخلی sys.getsizeof در اینجا مفید است:

import sys
print(f"list size: {sys.getsizeof([])} bytes")
print(f"dictionary size: {sys.getsizeof(dict)} bytes")
print(f"tuple size: {sys.getsizeof(())} bytes")
print(f"set size: {sys.getsizeof({})} bytes")

در اینجا خروجی است:

مشخصات حافظه برای انواع داده

همچنین می توانید از روش sys.getsizeof برای مقایسه اندازه حافظه یک تابع داخلی و سفارشی استفاده کنید.

به عنوان مثال، این تابع طول سفارشی را که از یک حلقه برای پایتون استفاده می کند با تابع len داخلی مقایسه کنید:

import sys

def getLength(iterable):
    count = 0

    for i in iterable:
        count +=1

    return count

print(f"Built-in length function: {sys.getsizeof(len)} bytes")
print(f"Custom length function: {sys.getsizeof(getLength)} bytes")

کد بالا خروجی زیر را می دهد:

مقایسه حافظه خروجی خط فرمان

با این حال، در حالی که sys.getsizeof اندازه یک شی را در حافظه اندازه گیری می کند، فقط خود شیء را محاسبه می کند و نه کسانی که به آن ارجاع می دهند. برای آن، به یک روش پروفایل دقیق تری نیاز دارید.

نمایه حافظه یک تابع پایتون را پیدا کنید

با استفاده از بسته memory_profiler می توانید مشخصات حافظه دقیق تری از هر خط کد یک تابع دریافت کنید. این شامل اضافه کردن دکوراتور @profile به عملکرد یا روش شما است:

import pandas
import numpy
from memory_profiler import profile

class Manipulate:
    @profile
    def manipulateData(self):
        df = pandas.DataFrame({
            'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
            'B' : [numpy.nan, "Pandas", numpy.nan, "Pandas", "Python", "JavaScript"],
        })

        df.fillna(method='bfill', inplace=True)
        df.fillna(method='ffill', inplace=True)
        return str(df)

manip = Manipulate()
print(manip.manipulateData())

کد بالا یک نمایه حافظه دقیق از هر خط کد در تابع به شرح زیر ارائه می دهد:

خروجی کد برای پروفایل حافظه خط به خط

ستون استفاده از Mem میزان استفاده از حافظه را برای یک خط کد خاص نشان می‌دهد، در حالی که ستون افزایش هزینه‌های سربار هر خط را نشان می‌دهد. ستون Occurrence تعداد دفعاتی را که یک خط کد حافظه را تخصیص داده یا تخصیص می دهد را مشخص می کند.

مطلب مرتبط:   7 بهترین فریم ورک برای ادغام و تست واحد در پایتون

به عنوان مثال، در خروجی بالا، خط 11 دو بار با افزایش حافظه 0.1 مگابایت (مبی بایت) اتفاق افتاد و میزان استفاده از حافظه را به 55.4 مگابایت افزایش داد. خطوط 19 و 22 نیز به ترتیب 0.2 مگابایت و 0.3 مگابایت کمک کردند که مجموع مصرف حافظه را به 55.9 مگابایت رساند.

نمایه حافظه یک اسکریپت پایتون را توسط Timestamp پیدا کنید

همچنین می‌توانید با اجرای دستور mprof در ترمینال مانند شکل، مشخصات حافظه کل اسکریپت پایتون را با استفاده از memory_profiler تخمین بزنید:

mprof run script_name.py

دستور بالا هر 0.1 ثانیه از اسکریپت مشخص شده نمونه برداری می کند و به طور خودکار یک فایل .dat در دایرکتوری پروژه فعلی شما ایجاد می کند.

نمایه حافظه یک اسکریپت پایتون

ارقامی که از نماد MEM پیروی می کنند، نمایه های استفاده از حافظه اسکریپت پایتون در یک بازه زمانی خاص هستند. آخرین شکل‌ها در سمت راست نشان‌دهنده مُهر زمانی است که نمایه‌ساز برای هر استفاده از حافظه گرفته است.

همچنین می توانید نموداری از نمایه حافظه را دریافت کنید. این به نصب matplotlib نیاز دارد:

pip install matplotlib

پس از نصب، دستور mprof را به صورت زیر اجرا کنید:

mprof plot

در اینجا خروجی در این مورد است:

خروجی طرح خط فرمان-1

نمایه حافظه اسکریپت را در یک فایل اختصاصی پایتون اجرا کنید

ممکن است بخواهید برای اسکریپت های مختلف پایتون پروفایل ایجاد کنید. شما می توانید این کار را با استفاده از یک ماژول اختصاصی پایتون از طریق فرآیند فرعی پایتون انجام دهید.

به این ترتیب، می توانید نمایه کننده حافظه خود را از پایه کد خود جدا کرده و خروجی نمودار را به صورت محلی ذخیره کنید:

import subprocess

subprocess.run([
    'mprof', 'run', '--include-children', 'missing.py'
])

# save the plot output locally
subprocess.run(['mprof', 'plot', '--output=output.jpg'])

برای اجرای نمایه حافظه اسکریپت، فقط باید فایل پایتون حاوی کد بالا را اجرا کنید. این یک نمودار نمایه حافظه (output.jpg) در فهرست فایل ایجاد می کند:

مطلب مرتبط:   کشف جنگو 5.0: برای سفر توسعه خود چه انتظاری داشته باشید

نمودار نمایه حافظه اسکریپت

مقدار حافظه استفاده شده از اجرای یک تابع را بیابید

با استفاده از بسته psutil می توانید مشخصات کلی حافظه یک روش یا تابع را در حین اجرا پیدا کنید.

به عنوان مثال، برای نمایه کردن روش دستکاری قبلی Pandas DataFrame در یک فایل پایتون دیگر:

import psutil
import sys
import os
sys.path.append(sys.path[0] + "/..")

# import the class containing your method
from somecode.missing import Manipulate

# instantiate the class
manip = Manipulate()

process = psutil.Process(os.getpid())
initial_memory = process.memory_info().rss

# run the target method:
manip.manipulateData()

# get the memory information after execution
final_memory = process.memory_info().rss
memory_consumed = final_memory - initial_memory
memory_consumed_mb = memory_consumed / (1024 * 1024)
print(f"Memory consumed by the function: {memory_consumed_mb:.2f} MB")

در بالا کل مشخصات حافظه روش را بر حسب مگابایت (MB) تخمین می زند که نشان داده شده است:

خط فرمان کل خروجی نمایه حافظه

نمایه حافظه یک خط کد را در نوت بوک Jupyter پیدا کنید

اگر از iPython در Jupyter Notebook استفاده می‌کنید، می‌توانید مشخصات حافظه یک لاینر را با استفاده از memory_profiler محاسبه کنید. شما فقط باید memory_profiler را در یک سلول بارگیری کنید. سپس تابع جادویی %memit را در سلول های بعدی به کد خود اضافه کنید. این حداکثر حافظه کد و اندازه افزایش یافته را برمی گرداند.

این روش با اسکریپت های معمولی پایتون علاوه بر iPython در Jupyter Notebook کار نمی کند.

مثلا:

کد و خروجی نوت بوک Jupyter

همچنین می‌توانید از تابع جادویی %memit در Jupyter Notebook برای نمایه کردن حافظه یک تابع در زمان اجرا استفاده کنید:

مشخصات حافظه عملکرد نوت بوک Jupyter

کارایی حافظه خود را در کد پایتون خود بهبود بخشید

با توجه به وظایف سنگینی که ما اغلب از پایتون برای آن ها استفاده می کنیم، هر خط کد به بهینه سازی کافی برای مدیریت استفاده از حافظه نیاز دارد. در حالی که پایتون دارای بسیاری از توابع داخلی پایتون است، اشیاء بدون مرجع منجر به نشت حافظه می شوند.

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