از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
مبانی مدیریت حافظه در پایتون
سرفصلهای مطلب
معرفی
مدیریت حافظه است process تخصیص کارآمد، عدم تخصیص و هماهنگی حافظه به طوری که تمام فرآیندهای مختلف به آرامی اجرا شوند و بتوانند به طور بهینه به منابع مختلف سیستم دسترسی داشته باشند. مدیریت حافظه همچنین شامل پاکسازی حافظه اشیایی است که دیگر به آنها دسترسی ندارید.
در پایتون، مدیر حافظه با اجرای دوره ای برای پاکسازی، تخصیص و مدیریت حافظه، مسئولیت این نوع وظایف را بر عهده دارد. برخلاف C، جاوا و سایر زبان های برنامه نویسی، پایتون اشیاء را با استفاده از شمارش مرجع مدیریت می کند. این بدان معنی است که مدیر حافظه تعداد ارجاعات به هر شی در برنامه را پیگیری می کند. هنگامی که تعداد مرجع یک شی به صفر می رسد، به این معنی که شی دیگر مورد استفاده قرار نمی گیرد، جمع کننده زباله (بخشی از مدیر حافظه) به طور خودکار حافظه را از آن شی خاص آزاد می کند.
کاربر نباید نگران مدیریت حافظه باشد process تخصیص و تخصیص حافظه کاملاً خودکار است. حافظه بازیابی شده می تواند توسط اشیاء دیگر استفاده شود.
مجموعه زباله پایتون
همانطور که قبلا توضیح داده شد، پایتون برای آزاد کردن فضای حافظه، اشیایی را که دیگر در برنامه به آنها ارجاع داده نمی شود، حذف می کند. این process که در آن پایتون بلوکهایی از حافظه را که دیگر استفاده نمیشوند آزاد میکند، Garbage Collection نامیده میشود. پایتون زباله روب (GC) در طول اجرای برنامه اجرا می شود و اگر تعداد مراجع به صفر کاهش یابد فعال می شود. اگر به یک شی یک نام جدید اختصاص داده شود یا در a قرار گیرد، تعداد مراجع افزایش می یابد containerمانند تاپل یا فرهنگ لغت. به طور مشابه، هنگامی که ارجاع به یک شی دوباره تخصیص داده می شود، زمانی که مرجع شی از محدوده خارج می شود، یا زمانی که یک شی حذف می شود، تعداد مراجع کاهش می یابد.
حافظه یک پشته است که شامل اشیاء و سایر ساختارهای داده مورد استفاده در برنامه است. تخصیص و توزیع این فضای پشته توسط مدیر حافظه پایتون با استفاده از توابع API کنترل می شود.
اشیاء پایتون در حافظه
هر متغیر در پایتون به عنوان یک شی عمل می کند. اشیاء می توانند ساده (شامل اعداد، رشته ها و غیره) و یا کانتینرها (فرهنگ لغت ها، لیست ها یا کلاس های تعریف شده توسط کاربر) باشند. علاوه بر این، پایتون یک زبان تایپ پویا است که به این معنی است که قبل از استفاده از متغیرها در برنامه نیازی به تعریف متغیرها یا انواع آنها نداریم.
مثلا:
>>> x = 5
>>> print(x)
5
>>> del x
>>> print(x)
Traceback (most recent call last):
File "<mem_manage>", line 1, in <module>
print(x)
NameError : name 'x' is not defined
اگر به 2 خط اول برنامه بالا نگاه کنید، اعتراض کنید x
شناخته شده است. وقتی شی را حذف می کنیم x
و سعی کنید از آن استفاده کنید، با خطای مبنی بر اینکه متغیر x
تعریف نشده است.
می بینید که جمع آوری زباله در پایتون کاملاً خودکار است و برنامه نویس برخلاف زبان هایی مانند C نیازی به نگرانی در مورد آن ندارد.
اصلاح زباله جمع کن
زباله جمع کن پایتون سه نسل دارد که اشیاء در آنها طبقه بندی می شوند. یک شی جدید در نقطه شروع چرخه زندگی خود اولین نسل زباله جمع کن است. از آنجایی که این شی از جمع آوری زباله جان سالم به در می برد، به نسل های بعدی منتقل می شود. هر یک از 3 نسل زباله جمع کن یک آستانه دارد. به طور خاص، زمانی که آستانه تعداد تخصیص منهای تعداد تخصیص تجاوز کند، آن نسل جمع آوری زباله را اجرا می کند.
نسلهای قبلی نیز زبالههایی هستند که بیشتر از نسلهای بالاتر جمعآوری میشوند. این به این دلیل است که اشیاء جدیدتر بیشتر از اشیاء قدیمی دور انداخته می شوند.
را gc
ماژول شامل توابعی برای تغییر مقدار آستانه، راه اندازی جمع آوری زباله است process به صورت دستی، جمع آوری زباله را غیرفعال کنید processو غیره می توانیم مقادیر آستانه نسل های مختلف زباله جمع کن را با استفاده از get_threshold()
روش:
import gc
print(gc.get_threshold())
خروجی نمونه:
(700, 10, 10)
همانطور که می بینید، در اینجا ما آستانه 700 برای نسل اول و 10 برای هر یک از دو نسل دیگر داریم.
ما می توانیم مقدار آستانه را برای راه اندازی جمع آوری زباله تغییر دهیم process با استفاده از set_threshold()
روش از gc
مدول:
gc.set_threshold(900, 15, 15)
در مثال بالا، مقدار آستانه را برای هر 3 نسل افزایش داده ایم. افزایش مقدار آستانه فرکانس اجرای زباله جمع کن را کاهش می دهد. به طور معمول، ما به عنوان یک توسعه دهنده نیازی به فکر کردن زیاد در مورد جمع آوری زباله پایتون نداریم، اما این ممکن است هنگام بهینه سازی زمان اجرا پایتون برای سیستم هدف شما مفید باشد. یکی از مزایای کلیدی این است که مکانیسم جمعآوری زباله پایتون بسیاری از جزئیات سطح پایین را به طور خودکار برای توسعهدهنده کنترل میکند.
چرا جمع آوری زباله دستی انجام شود؟
می دانیم که مفسر پایتون ردیابی ارجاعات به اشیاء مورد استفاده در یک برنامه را نگه می دارد. در نسخه های قبلی پایتون (تا نسخه 1.6)، مفسر پایتون فقط از مکانیسم شمارش مرجع برای مدیریت حافظه استفاده می کرد. هنگامی که تعداد مراجع به صفر می رسد، مفسر پایتون به طور خودکار حافظه را آزاد می کند. این مکانیسم شمارش مرجع کلاسیک بسیار مؤثر است، با این تفاوت که در زمانی که برنامه کار می کند، کار نمی کند چرخه های مرجع. اگر یک یا چند شی به یکدیگر ارجاع داده شوند، چرخه مرجع اتفاق میافتد و از این رو تعداد مراجع هرگز به صفر نمیرسد.
بیایید یک مثال را در نظر بگیریم.
>>> def create_cycle():
... list = (8, 9, 10)
... list.append(list)
... return list
...
>>> create_cycle()
(8, 9, 10, (...))
کد بالا یک چرخه مرجع ایجاد می کند، جایی که شی list
به خود اشاره دارد. از این رو، حافظه برای شی list
با بازگشت عملکرد به طور خودکار آزاد نمی شود. مشکل چرخه مرجع با شمارش مرجع قابل حل نیست. با این حال، این مشکل چرخه مرجع را می توان با تغییر رفتار جمع کننده زباله در برنامه پایتون خود حل کرد.
برای این کار می توانیم از gc.collect()
عملکرد از gc
مدول.
import gc
n = gc.collect()
print("Number of unreachable objects collected by GC:", n)
را gc.collect()
تعداد اشیایی را که جمع آوری کرده و تخصیص داده است برمی گرداند.
دو روش برای جمعآوری دستی زباله وجود دارد: جمعآوری زباله مبتنی بر زمان یا رویداد.
جمع آوری زباله مبتنی بر زمان بسیار ساده است: gc.collect()
تابع پس از یک بازه زمانی ثابت فراخوانی می شود.
گردآوری زباله مبتنی بر رویداد به نام gc.collect()
عملکرد پس از رخ دادن یک رویداد (یعنی زمانی که برنامه خارج می شود یا برنامه برای یک دوره زمانی خاص بیکار می ماند).
بیایید با ایجاد چند چرخه مرجع، کار جمع آوری زباله دستی را درک کنیم.
import sys, gc
def create_cycle():
list = (8, 9, 10)
list.append(list)
def main():
print("Creating garbage...")
for i in range(8):
create_cycle()
print("Collecting...")
n = gc.collect()
print("Number of unreachable objects collected by GC:", n)
print("Uncollectable garbage:", gc.garbage)
if __name__ == "__main__":
main()
sys.exit()
خروجی به صورت زیر است:
Creating garbage...
Collecting...
Number of unreachable objects collected by GC: 8
Uncollectable garbage: ()
اسکریپت بالا یک شی لیست ایجاد می کند که توسط متغیری با نام خلاقانه به آن اشاره می شود list
. اولین عنصر شی لیست به خودش اشاره دارد. تعداد مراجع شی لیست همیشه بزرگتر از صفر است حتی اگر در برنامه حذف شده یا خارج از محدوده باشد. از این رو list
شی به دلیل مرجع دایره ای زباله جمع آوری نمی شود. مکانیسم جمعآوری زباله در پایتون بهطور خودکار منابع دایرهای را بررسی و جمعآوری میکند.
در کد بالا، از آنجایی که تعداد مراجع حداقل 1 است و هرگز نمی تواند به 0 برسد، ما با فراخوانی اشیا را به زور زباله جمع آوری کرده ایم. gc.collect()
. با این حال، به یاد داشته باشید که مرتباً زباله جمع آوری نکنید. دلیل آن این است که حتی پس از آزاد کردن حافظه، GC برای ارزیابی واجد شرایط بودن شی برای جمعآوری زباله زمان میبرد و زمان و منابع پردازنده را اشغال میکند. همچنین، به یاد داشته باشید که جمعآوری زباله را تنها پس از شروع کامل برنامه به صورت دستی مدیریت کنید.
نتیجه
در این مقاله، روش مدیریت حافظه در پایتون به طور خودکار با استفاده از شمارش منابع و استراتژیهای جمعآوری زباله بحث کردیم. بدون جمع آوری زباله، پیاده سازی یک مکانیسم مدیریت حافظه موفق در پایتون غیرممکن است. همچنین، برنامه نویسان نباید نگران حذف حافظه اختصاص داده شده باشند، زیرا توسط مدیر حافظه پایتون مراقبت می شود. این منجر به نشت حافظه کمتر و عملکرد بهتر می شود.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-21 00:10:04