Я пытаюсь улучшить свое понимание того, как работает управление памятью в 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 все еще существует, и поэтому она должна существовать в одном из поколений?
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
. Когда эти объекты создаются, сборщик мусора запускается автоматически.