Понимание генерации сборки мусора Cpython

Я пытаюсь улучшить свое понимание того, как работает управление памятью в python, и меня смущает концепция поколений в модуле сборщика мусора python.

Мое понимание заключается в следующем:

Все созданные объекты начинаются с поколения 0, как только будет достигнуто пороговое значение (700 по умолчанию для поколения 0), python запустит коллекцию в этом поколении, и любые уцелевшие объекты перейдут в следующее поколение.

Учитывая вышеизложенное, я не могу понять приведенный ниже вывод.

import gc
import sys
x = 1
print(gc.get_count())
gc.collect()
print(gc.get_count())

Выход

(64, 1, 1)
(0, 0, 0)

Во-первых, я запустил только 1 строку кода, и у меня уже есть объекты в поколениях 1 и 2, что означает, что сборка мусора уже произошла как минимум дважды, как это возможно? Можно ли как-то узнать, какие объекты находятся в каждом поколении? Во-вторых, Почему у меня 0 ссылок во всех поколениях после сбора? Я все еще могу запустить команду print(x) и не получить ошибку. Не означает ли это, что ссылка на x все еще существует, и поэтому она должна существовать в одном из поколений?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
148
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

gc.get_count() показывает счетчик для каждого поколения ближе к порогу.

Это не количество объектов в каждом поколении, а счетчик, который, когда он достигает threadshold, будет происходить сбор для этого поколения.

Например, если я начну с (0,0,0) на счетчике, запуск x = [[] for i in range(100)] установит счетчик на (101,0,0).

Запуск y = [[] for i in range(600)] приведет к тому, что счетчик переключится на (0,1,0), и начнется сбор gen0. На данный момент все мои списки переместятся в gen1, поскольку они пережили коллекцию gen0.

Когда счетчик достигает (699,699,0) и выделяется другой объект, происходит сбор gen0 и gen1, и счетчик переходит к (0,0,1). Когда счетчик достигает (699,699,699) и объект выделяется, или вы используете gc.collect() (который запускает сбор gen2), счетчик сбрасывается обратно на (0,0,0).

Чтобы получить объекты в каждом поколении, используйте gc.get_objects(gen).

Что касается сборки мусора перед запуском вашего кода - когда Python запускается, он создает множество объектов еще до загрузки вашего скрипта. Например, вы можете увидеть загруженные модули, запустив sys.modules. Когда эти объекты создаются, сборщик мусора запускается автоматически.

Другие вопросы по теме