Garbage Collection پایتون چیست و چطور کار می‌کند؟

دوشنبه 27 اردیبهشت 1400

پایتون یکی از محبوب ترین زبان های برنامه نویسی است و کاربرد آن همچنان در حال رشد است. در سال 2021 به دلیل سرعت رشدش در رتبه سوم "زبان TIOBE سال" قرار گرفت. سهولت استفاده از پایتون و جامعه گسترده، آن را به مکانی مناسب برای تحلیل داده‌ها، برنامه های وب، و خودکارسازی کار تبدیل کرده است.

Garbage Collection پایتون چیست و چطور کار می‌کند؟

در این مقاله، ما به جزئیات garbage collection یا به عبارتی بازیابی حافظه در پایتون می‌پردازیم. سپس بررسی می‌کنیم پایتون چطور garbage collection را اجرا می‌کند.

garbage collection پایتون چیست و چرا به آن نیاز داریم؟

اگر پایتون اولین زبان برنامه نویسی شما است، ممکن است ایده garbage collection برای شما بیگانه باشد. بیاید با اصول اولیه شروع کنیم.

مدیریت حافظه

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

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

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

این کار منجر به دو مشکل می‌شود:

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

2. آزادسازی خیلی زود حافظه. مشکل نوع دوم این است که حافظه را خیلی زود آزاد می‌کنید در حالی که هنوز از آن استفاده می‌کنید. اگر برنامه سعی کند به یک متغیر در حافظه دسترسی پیدا کند که وجود ندارد، یا باعث خراب شدن داده‌های شما شود، می‌تواند منجر به کرش شدن برنامه شما شود. متغیری که به حافظه آزاد شده اشاره دارد dangling pointe نامیده می‌شود.

این مشکلات نامطلوب بودند، و بنابراین زبان‌های جدید مدیریت خودکار حافظه را اضافه کردند.

مدیریت خودکار حافظه و بازیابی حافظه (garbage collection)

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

چند روش مختلف برای مدیریت خودکار حافظه وجود دارد. موارد معروف از شمارش ارجاع (Reference counting) استفاده می‌کنند. با شمارش ارجاع، runtime تمام ارجاعات به یک آبجکت را ردیابی می‌کند. وقتی یک آبجکت ارجاع صفر به آن دارد، توسط کد برنامه غیر قابل استفاده است و می‌تواند حذف شود.

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

با این حال، مدیریت خودکار حافظه هزینه دارد. برنامه شما برای ردیابی همه ارجاعات خود باید از محاسبات و حافظه اضافی استفاده کند. به علاوه، بسیاری از زبان‌های برنامه نویسی با مدیریت خودکار حافظه از فرآیند "stop-the-world" برای بازیابی حافظه استفاده می‌کنند که در حالی که garbage collector به دنبال آبجکت‌ها و حذف آن‌هاست همه اجراها را متوقف می‌کند.

با پیشرفت پردازش کامپیوتر از قانون Moore و مقدار بیشترRAM  در رایانه های جدید، مزایای مدیریت خودکار حافظه معمولا بیشتر از نکات منفی آن است. بنابراین بیشتر زبان‌های برنامه نویسی مدرن مانند پایتون، جاوا و Golang از مدیریت حافظه خودکار استفاده می‌کنند.

پایتون چگونه garbage collection را پیاده سازی می‌کند

در این قسمت به نحوه کار garbage collection در پایتون می‌پردازیم.

در اینجا ما فرض می‌کنیم که شما از پیاده سازی CPython استفاده می‌کنید. CPython بیشترین کاربرد را دارد. با این حال، پیاده سازی های دیگری از پایتون وجود دارد، مانند PyPy، Jython (مبتنی بر جاوا)، یا IronPython (مبتنی بر C#).

برای دیدن اینکه از کدام پایتون استفاده می‌کنید، دستور زیر را در ترمینال خود (Linux) اجرا کنید:

>>>python -c 'import platform; print(platform.python_implementation())'

Or, you can have these lines for both Linux and Windows terminals.
>>> import platform
>>> print(platform.python_imlplementation())
CPython

مدیریت حافظه و garbage collection در CPython دو جنبه دارد:

شمارش ارجاع (Reference counting)

Generational garbage collection

بیاید هر یک از این موارد را بررسی کنیم.

شمارش ارجاع در CPython

مکانیسم اصلی garbage collection در CPython از طریق شمارش ارجاع است. هر زمان که یک آبجکت را در پایتون می‌‌سازید، C object اصلی هم نوع پایتون را دارد (مثل list، dict، یا function) و هم تعداد ارجاع را دارد.

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

کد برنامه شما نمی‌تواند شمارش ارجاع پایتون را غیر فعال کند. این در مقایسه با generational garbage collector است که در زیر بحث شده است.

برخی افراد ادعا می‌کنند که reference counting برای بازیابی حافظه ضعیف عمل می‌کند. شمارش ارجاعات مشکلاتی دارد، از جمله عدم توانایی در شناسایی رفرنس‌های دوره‌ای. با این حال، شمارش ارجاع خوب است زیرا می‌توانید یک آبجکت را وقتی که دیگر ارجاعی به آن وجود ندارد حذف کنید.

Generational garbage collection

علاوه بر استراتژی reference counting برای مدیریت حافظه، پایتون از روشی به نام generational garbage collector نیز استفاده می‌کند.

آسان‌ترین راه برای درک اینکه چرا ما به یک generational garbage collector نیاز داریم با یک مثال است.

در بخش قبل دیدیم افزودن یک آبجکت به یک آرایه یا آبجکت تعداد ارجاع را افزایش می‌دهد. اما اگر آبجکتی را به خودش اضافه کنید چه اتفاقی می‌افتد؟

>>> class MyClass(object):
...     pass
...
>>> a = MyClass()
>>> a.obj = a
>>> del a

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

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

ما این نوع مشکلات را چرخه ارجاع می‌نامیم و شما نمی‌توانید با شمارش ارجاع آن را حل کنید. این نقطه generational garbage collector است، که توسط ماژول gc در کتابخانه استاندارد در دسترس است.

جمع بندی

در این مقاله با Garbage Collection پایتون آشنا شدیم. بازیابی حافظه یا همان Garbage Collection برای هر برنامه ای لازم و ضروری است. خودکارسازی مدیریت حافظه می‌تواند کمک زیادی به توسعه دهندگان کند. از این رو برنامه نویسان به طور کلی زمان کمی را صرف بحث در مورد مدیریت حافظه و پیاده سازی آن در برنامه می‌کنند و این امر می‌تواند بسیار مفید باشد.

پایتون بیشتر قسمت های سخت مدیریت حافظه را برای شما انجام می‌دهد، اما دانستن شیوه کار آن همچنان مفید است.

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • Python
  • 1k بازدید
  • 1 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید