Збір сміття в Python: усе, що вам потрібно знати

pic
](https://leapcell.io/?lct=mpyg)

I. Огляд збору сміття

  • У комп'ютерних науках збір сміття (Garbage Collection, абревіатура GC) — це автоматичний механізм управління пам'яттю. Коли певний простір пам'яті, зайнятий програмою, більше не використовується, програма повертає його операційній системі за допомогою алгоритмів збору сміття.
  • Збирач сміття зменшує навантаження на програмістів і мінімізує помилки програми. Його корені йдуть з мови LISP.
  • В даний час багато мов, таких як Smalltalk, Java, C#, Go і D, підтримують збір сміття.
  • Як механізм автоматичного управління пам'яттю в сучасних мовах програмування, GC виконує два основні завдання:
    • Ідентифікує непотрібні ресурси сміття в пам'яті.
    • Очищає ці ресурси сміття і звільняє пам'ять для інших об'єктів.
  • Це звільняє програмістів від важкої роботи з управління ресурсами, дозволяючи їм зосередитись більше на бізнес-логіці. Однак програмісти все ж повинні розуміти GC, що допомагає їм писати більш надійний код.

II. Загальні алгоритми збору сміття

Підрахунок посилань:

  • Для кожного об'єкта підтримується лічильник посилань. Коли об'єкт, що посилається на цей об'єкт, знищується, лічильник посилань зменшується на одиницю. Коли лічильник посилань об'єкта досягає нуля, об'єкт звільняється.
  • Представники мов: Python, PHP, Swift.
  • Переваги: Швидке звільнення об'єктів, і звільнення відбувається не тільки коли пам'ять вичерпується або досягається певний поріг.
  • Недоліки: Невміє ефективно обробляти кругові посилання, а підтримка лічильника посилань в реальному часі накладає накладні витрати.

Метод позначення та очищення (Mark-Sweep):

  • Перебираються всі об'єкти, на які є посилання, починаючи з кореневого змінного, позначаються посиланням об'єкти, а ті, що не позначені, очищаються.
  • Представники мов: Golang (метод трикольорового позначення), Python (допоміжний).
  • Переваги: Це долає недоліки підрахунку посилань.
  • Недоліки: Потрібно здійснювати STW (тимчасову зупинку програми).

Колекція поколінь:

  • Розділення простору для різних поколінь в залежності від тривалості життя об'єктів. Об'єкти з тривалішим життям потрапляють до старшого покоління, а об'єкти з коротким — до нового покоління. Різні покоління мають різні алгоритми і частоту очищення.
  • Представники мов: Java, Python (допоміжний).
  • Переваги: Хороша продуктивність очищення.
  • Недоліки: Алгоритм складний.

III. Механізм збору сміття в Python

Опис з офіційної документації:

  • Деталі управління пам'яттю Python залежать від реалізації.
  • CPython використовує підрахунок посилань для виявлення недоступних об'єктів і використовує інший механізм для збору циклів посилань. Він періодично виконує алгоритм виявлення циклів для знаходження недоступних циклів і видалення пов'язаних об'єктів.
  • Модуль gc надає функції для виконання збору сміття, отримання статистики налагодження та оптимізації параметрів збирача.
  • Інші реалізації (наприклад, Jython або PyPy) можуть використовувати різні механізми, такі як повний збірник сміття. Якщо код Python залежить від поведінки, реалізованої підрахунком посилань, це може призвести до проблем з портативністю.

Підрахунок посилань:

  • Механізм збору сміття, який за замовчуванням використовується в Python, — це метод підрахунку посилань, який був вперше запропонований Джорджем Е. Коллінсом у 1960 році і досі використовується багатьма мовами програмування.
  • Принцип: Кожен об'єкт має поле ob_ref, яке зберігає кількість посилань на об'єкт. Коли нове посилання вказує на об'єкт, ob_ref збільшується на одиницю. Коли посилання стає недійсним, ob_ref зменшується на одиницю.
    Коли лічильник посилань досягає нуля, об'єкт одразу звільняється, і зайнятий простір пам'яті звільняється.
  • Недоліки: Необхідно додатково зберігати інформацію про лічильник посилань і не можна ефективно вирішити проблему "кругових посилань". Наприклад:
a = {} # Лічильник посилань об'єкта A дорівнює 1  
b = {} # Лічильник посилань об'єкта B дорівнює 1  
a['b'] = b # Лічильник посилань на B збільшується на 1  
b['a'] = a # Лічильник посилань на A збільшується на 1  
del a # Лічильник посилань на A зменшується на 1, і остаточний лічильник посилань на A дорівнює 1  
del b # Лічильник посилань на B зменшується на 1, і остаточний лічильник посилань на B дорівнює 1

pic

  • В наведеному прикладі, після виконання команд del, об'єкти A та B утворюють кругове посилання. Незважаючи на те, що зовнішніх посилань немає, лічильник посилань не дорівнює нулю, тому вони не будуть звільнені, що може призвести до витоку пам'яті.

Метод позначення та очищення (Mark-Sweep):

  • Це алгоритм збору сміття, який реалізується на основі технології трасування GC і складається з двох фаз:
    • Фаза позначення: Позначити всі "активні об'єкти".
    • Фаза очищення: Очищати "неактивні об'єкти", які не були позначені.
  • Починаючи від кореневих об'єктів (наприклад, глобальні змінні, стек викликів та регістри), здійснюється перехід по об'єктах уздовж спрямованих ребер. Доступні об'єкти позначаються як активні, а недоступні об'єкти позначаються як неактивні і потім очищуються.
  • Алгоритм позначення та очищення, як допоміжна технологія збору сміття в Python, в основному обробляє контейнерні об'єкти (наприклад, list, dict, tuple, instance тощо), оскільки строкові та числові об'єкти не викликають проблем з круговими посиланнями.
  • Python використовує двосторонньо зв'язаний список для організації цих контейнерних об'єктів.
  • Недоліки: Необхідно послідовно сканувати всю пам'ять купи перед очищенням неактивних об'єктів. Навіть якщо залишилося лише кілька активних об'єктів, потрібно сканувати всі об'єкти.

Колекція поколінь:

  • Це режим роботи, який обмінює простір на час. Пам'ять поділяється на різні набори в залежності від часу життя об'єкта, і кожен набір вважається поколінням. Python поділяється на три покоління: молодше покоління (покоління 0), середнє покоління (покоління 1) та старше покоління (покоління 2), що відповідають трьом зв'язаним спискам. Частота збору сміття зменшується, коли час життя об'єкта збільшується.
  • Новостворені об'єкти розміщуються в молодшому поколінні. Коли загальна кількість елементів у зв'язаному списку молодшого покоління досягає верхнього ліміту, спрацьовує механізм збору сміття. Об'єкти, які підлягають очищенню, очищаються, а ті, що не підлягають очищенню, переміщуються в середнє покоління, і так далі. Об'єкти в старшому поколінні переживають найдовше.
  • Колекція поколінь базується на технології позначення та очищення і також використовується як допоміжна технологія збору сміття в Python для обробки контейнерних об'єктів.

pic

IV. Витік пам'яті

  • Витоки пам'яті досить рідкісні в повсякденному використанні Python.
  • Ситуації, коли CPython не звільняє всю пам'ять після завершення:
    • Об'єкти, на які є посилання з глобального простору імен або з Python-модулів, не завжди звільняються, що може статися у разі кругових посилань.
      Деяка пам'ять, виділена бібліотеками C, також може не бути звільнена.
  • Python очистить пам'ять і спробує знищити кожен об'єкт під час завершення роботи.
  • Якщо ви хочете примусити Python видалити певний вміст при виході, можна використовувати модуль atexit для виконання функції.
  • Приклад коду:
# У деяких реалізаціях Python наступний код (який добре працює в CPython) може вичерпати дескриптори файлів  
for file in very_long_list_of_files:  
 f = open(file)  
 c = f.read(1)
  • Покращене рішення:
# Ви повинні явно закривати файл або використовувати оператор with, що ефективно незалежно від схеми керування пам'яттю  
for file in very_long_list_of_files:  
 with open(file) as f:  
 c = f.read(1)

Leapcell: Найкраща серверна платформа для хостингу Python додатків


pic

Нарешті, дозвольте представити найкращу платформу для розгортання Python сервісів: Leapcell

1. Підтримка кількох мов програмування

  • Розробляйте, використовуючи JavaScript, Python, Go або Rust.

2. Розгортання необмеженої кількості проєктів безкоштовно

  • Платіть лише за фактичне використання — без оплат за відсутність запитів.

3. Неперевершена ефективність витрат

  • Сплата по факту використання без плат за простоювання.
  • Приклад: За $25 ви можете підтримувати 6,94 мільйона запитів зі середнім часом відповіді 60 мілісекунд.

4. Спрощений досвід для розробників

  • Інтуїтивно зрозумілий інтерфейс для легкого налаштування.
  • Повністю автоматизовані CI/CD пайплайни та інтеграція з GitOps.
  • Реальний моніторинг та журналювання для корисних інсайтів.

5. Легкість масштабування та висока продуктивність

  • Автоматичне масштабування для легкого оброблення високої кількості запитів.
  • Нульова операційна навантаженість — зосередьтеся лише на створенні.


pic

Документація доступна тут!

Leapcell Twitter: https://x.com/LeapcellHQ

Перекладено з: Python Garbage Collection: Everything You Need to Know

Leave a Reply

Your email address will not be published. Required fields are marked *