برنامه نویسی

مدیریت حافظه در پایتون – انجمن DEV 👩‍💻👨‍💻

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

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

اهمیت مدیریت حافظه

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

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

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

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

زبان‌های برنامه‌نویسی اولیه مانند C و C++ از توسعه‌دهندگان می‌خواستند که حافظه را با تخصیص دستی و حذف حافظه هنگام کدنویسی مدیریت کنند. این روش ناکارآمد است زیرا گاهی اوقات توسعه دهندگان می توانند ناخودآگاه یکی از فرآیندها را نادیده بگیرند و با برنامه خود دچار مشکل شوند.

در پایتون، مدیریت حافظه به طور خودکار توسط مدیر حافظه پایتون مدیریت می شود. مانند سایر زبان ها، مدیر حافظه پایتون از حافظه پشته و پشته استفاده می کند.

  1. پشته حافظه: حافظه پشته داده های موقت، فراخوانی های تابع و ارجاع به اشیاء ذخیره شده در حافظه پشته را ذخیره می کند. اطلاعات بیشتر در مورد حافظه پشته را اینجا بخوانید.

  2. حافظه هیپ: حافظه Heap اشیاء و داده هایی را که باید بیشتر از حافظه پشته در حافظه باشند ذخیره می کند. این مقاله بیشتر در مورد حافظه پشته صحبت می کند.

این تصویر یک نمای کلی از آنچه هر حافظه در پایتون ذخیره می کند ارائه می دهد.

حافظه پشته در مقابل حافظه پشته

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

age = 20
score = 20
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در برنامه بالا، شما انتظار دارید که هر دو متغیر دارای فضای حافظه منحصر به فرد باشند زیرا اهداف متفاوتی را انجام می دهند. با این حال، مدیر حافظه پایتون این کار را انجام نمی دهد. از آنجایی که هر دو متغیر دارای مقدار یکسانی هستند، مدیر حافظه یک شی ایجاد می کند که هر دو مرجع را نشان می دهد. این تصویر نمای واضحی را نشان می دهد:

توضیحات تصویر

برای تایید این موضوع، از id() عملکرد در پایتون به این صورت است:

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

در مورد این رویکرد باید به نکاتی توجه کرد:

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

  2. به انواع داده های قابل تغییر مانند لیست ها، اشیاء متفاوتی اختصاص داده می شود، حتی اگر حاوی موارد مشابه باشند. این به این دلیل است که تغییرات در یکی از این لیست‌ها بر روی لیست(های) دیگر تأثیر می‌گذارد اگر در همان مکان حافظه باشند.

جمع آوری زباله در پایتون

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

  1. شمارش مرجع

  2. جمع آوری زباله نسلی

شمارش مراجع در پایتون

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

x = "This is my house!"
y = "This is my house!"
z = x
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

از آنجایی که متغیرها x، y، و z به مقادیر یکسان مراجعه کنید، آنها مکان حافظه یکسانی دارند. با این حال، تعداد مرجع متغیر x با هر تکلیف جدید افزایش می یابد. شما می توانید تعداد مرجع یک شی را با استفاده از عبارت بدست آورید sys.getrefcount() تابع موجود در sys مدول. می‌توانید تعداد مراجع قطعه کد بالا را در زیر تأیید کنید:

برخی از مواردی که باید توجه داشته باشید عبارتند از:

  1. را sys.getrefcount() تابع یک مرجع اضافی به تعداد اضافه می کند. این بدان معناست که اگر مرجع اولیه یک شی 1 باشد، sys.getrefcount() بازگشت خواهد کرد 2.

  2. در صورت تخصیص مجدد یکی از متغیرها، تعداد مراجع 1 کاهش می یابد.

  3. وقتی تعداد مرجع به 0 رسید، شی از حافظه جدا می شود.

برای کسب اطلاعات بیشتر در مورد شمارش مراجع باید این مقاله و این مقاله را بخوانید.

جمع آوری زباله نسلی

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

هنگامی که دو شی در حافظه به یکدیگر ارجاع دارند، به آن چرخه مرجع می گویند. اگر این اتفاق بیفتد، تعداد مرجع اشیاء به 0 نمی رسد و حافظه نیز آزاد نخواهد بود. در زیر مثالی از نحوه گیر کردن یک شی در یک چرخه مرجع آورده شده است:

superheroes = ["Captain America","Superman","Batman"]

sidekicks = ["Bucky", "Jimmy Oslen", "Robin"]

superheroes.append(sidekicks)
sidekicks.append(superheroes)

del superheroes

print(sidekicks[-1])
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کد بالا، حتی بعد از متغیر، superheroes حذف شده است، هنوز یک مرجع در حافظه دارد. وقتی آخرین عنصر متغیر را چاپ می کنید، می توانید این را تأیید کنید. sidekicks. همین اتفاق خواهد افتاد اگر sidekicks حذف شد یا اگر هر دو متغیر حذف شوند. کد بالا را می توانید در اینجا اجرا کنید:

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

زباله جمع کن به دلایل زیر همیشه نمی تواند کار کند:

  1. هیچ چیز دیگری در برنامه نمی تواند هر زمان که زباله جمع کن در حال اجرا باشد تا زمانی که کار انجام شود اجرا شود. این رفتار می تواند کد شما را کند کند.
  2. زباله جمع کن معمولاً کاری برای انجام ندارد زیرا چرخه های مرجع عمدتاً فقط در پروژه های بزرگ مشاهده می شوند.

برای استفاده از زباله جمع کن، باید آن را به صورت زیر وارد کنید:

import gc
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جمع کننده زباله اشیاء پایتون را به سه دسته به نام نسل ها طبقه بندی می کند. هر یک از این نسل ها دارای یک تعداد آستانه شی هستند. شمارش آستانه برای هر نسل را می توان با استفاده از gc.get_threshold() فرمان

import gc
print(gc.get_threshold())
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

700 برای نسل اول، 10 برای نسل دوم، 10 برای نسل سوم

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

اگر اشیا در یک نسل خاص پاکسازی نشوند زیرا هنوز ارجاع دارند، به نسل بعدی منتقل می‌شوند. برای فعال کردن دستی زباله جمع کن، از gc,collect() تابع.

import gc
gc.collect()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتیجه.

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

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

  1. حافظه هیپ – https://www.geeksforgeeks.org/what-is-a-memory-heap/

  2. پشته حافظه – https://www.sciencedirect.com/topics/engineering/stack-memory

  3. زباله جمع کن – https://docs.python.org/3/library/gc.html

  4. شمارش مراجع – https://betterprogramming.pub/a-guide-to-reference-counting-in-python-27334fc2e3c1

  5. شمارش مراجع – https://towardsdatascience.com/understanding-reference-counting-in-python-3894b71b5611

برای مطالب بیشتر از این دست، من را در هشنود دنبال کنید و توییتر.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا