Garbage collector
and a bit of memory
management
Cyril @notorca Lashkevich

piątek, 27 września 13
Модели управления
памятью
• Вручную
• Подсчет ссылок
• Garbage Collector

piątek, 27 września 13
Ручное управление

piątek, 27 września 13
Ручное управление
• Переменные на
стеке

piątek, 27 września 13
Ручное управление
• Переменные на
стеке

• alloca

piątek, 27 września 13
Ручное управление
• Переменные на
стеке

• alloca
• Масивы переменной
длинны (C99)

piątek, 27 września 13
Ручное управление
• Переменные на
стеке

• alloca
• Масивы переменной
длинны (C99)

• malloc/free
piątek, 27 września 13
Подсчет ссылок

piątek, 27 września 13
Подсчет ссылок
• retain(INCREF)/

release(DECREF)

piątek, 27 września 13
Подсчет ссылок
• retain(INCREF)/

release(DECREF)

• autoreleasepool

piątek, 27 września 13
Подсчет ссылок
• retain(INCREF)/

release(DECREF)

• autoreleasepool
• weak
piątek, 27 września 13
DAG
(directed acyclic graph)

• Задача

программиста не
допускать циклов в
графе объектов

piątek, 27 września 13
DAG
(directed acyclic graph)

• Задача

программиста не
допускать циклов в
графе объектов

piątek, 27 września 13
DAG
(directed acyclic graph)

• Задача

программиста не
допускать циклов в
графе объектов

piątek, 27 września 13
Что делать если циклы
нужны?

piątek, 27 września 13
Что делать если циклы
нужны?
• Пример: граф с
циклами

piątek, 27 września 13
Что делать если циклы
нужны?
• Пример: граф с
циклами

• Приходится

устранять циклы
вручную

piątek, 27 września 13
Что делать если циклы
нужны?
• Пример: граф с
циклами

• Приходится

устранять циклы
вручную

piątek, 27 września 13
Что делать если циклы
нужны?
• Пример: граф с
циклами

• Приходится

устранять циклы
вручную

piątek, 27 września 13
Что делать если циклы
нужны?
• Пример: граф с
циклами

• Приходится

устранять циклы
вручную

piątek, 27 września 13
Weak-ссылки
• Не увеличивают
счетчик ссылок
объекта

• Автоматически

зануляются при
уничтожении
объекта

piątek, 27 września 13
Python sys.getrefcount()
import sys
one = []
print 'At start
:',
sys.getrefcount(one)
two = one
print 'Second reference :',
sys.getrefcount(one)
del two
print 'After del
:',
sys.getrefcount(one)

piątek, 27 września 13
Python sys.getrefcount()
import sys
one = []
print 'At start
:',
sys.getrefcount(one)
two = one
print 'Second reference :',
sys.getrefcount(one)
del two
print 'After del
:',
sys.getrefcount(one)

piątek, 27 września 13

At start
: 2
Second reference : 3
After del
: 2
Анализ графа объектов
• Функции для анализа в модуле gc
• gc.get_referrers(*objs)
• gc.get_referents(*objs)
• Native-объекты должны предоставлять метод
tp_traverse

piątek, 27 września 13
Модуль weakref
• Слабые ссылки с callback на удаление объекта
• Proxy-объекты бросающие исключение при

использовании удаленного объекта (not hashable!)

• WeakValue и WeakKey словари
• WeakSet (3.2)
piątek, 27 września 13
In [11]: obj = ExpensiveObject()
In [12]: r = weakref.ref(obj)
In [15]: print('obj:', obj)
obj: <__main__.ExpensiveObject object at 0x108ea24d0>
In [16]: print('ref:', r)
ref: <weakref at 0x108eb62b8; to 'ExpensiveObject' at
0x108ea24d0>
In [17]: print('r():', r())
r(): <__main__.ExpensiveObject object at 0x108ea24d0>
In [18]: del obj
Deleting Expencive object
In [19]: print('r():', r())
r(): None
piątek, 27 września 13
Ограничения
• Не все типы могут быть weak: string, list,
tuple...

• Native-объекты должны реализовывать

поддержку (через tp_weaklistoffset )

• Осторожно с weak словарями!
piątek, 27 września 13
Garbage Collector
• Удаляет объекты,

недостижимые по
ссылкам из
корневого объекта
но с ненулевым
счетчиком ссылок

piątek, 27 września 13
GC в python
• Запускается когда колличество созданых

объектов поколения превышает количество
удаленных на х (по умолчанию 700, 10, 10)

• Либо вручную gc.collect()
• Low memory, idle не инициируют сборку
мусора

• Может работать долго
piątek, 27 września 13
Generations and thresholds

piątek, 27 września 13
Generations and thresholds
• 3 "поколения" (списка) объектов: 0,

piątek, 27 września 13

1, 2
Generations and thresholds
• 3 "поколения" (списка) объектов: 0, 1,
• Новые объекты попадают в 0 (не все)

piątek, 27 września 13

2
Generations and thresholds
• 3 "поколения" (списка) объектов: 0, 1,
• Новые объекты попадают в 0 (не все)
• Сборка мусора работает по поколениям

piątek, 27 września 13

2
Generations and thresholds
• 3 "поколения" (списка) объектов: 0, 1,
• Новые объекты попадают в 0 (не все)
• Сборка мусора работает по поколениям
• Объекты пережившие сборку мусора
переносятся в поколение +1

piątek, 27 września 13

2
Generations and thresholds
• 3 "поколения" (списка) объектов: 0, 1,
• Новые объекты попадают в 0 (не все)
• Сборка мусора работает по поколениям
• Объекты пережившие сборку мусора

2

переносятся в поколение +1

• Поколение 1 проверяется после threshold1
обработок поколения 0

piątek, 27 września 13
Ограничения GC
• Объекты с определенным __del__ не
уничтожаются GC (он не знает в каком
порядке их вызвать)

• Native-объекты которые могут содержать
ссылки должны правильно реализовывать
tp_traverse

piątek, 27 września 13
Проблемы с __del__
• Может создать циклические ссылки с

sys.exc_traceback и
sys.last_traceback (их нужно явно
занулить)

• Исключения в __del__ игнорируются с
выводом сообщения на stderr

• Не вызывается при завершении программы
piątek, 27 września 13
Удаление неудаляемых
объектов
• Вызвать gc.collect() что бы явно

запустить сборку мусора (вернет количество
удаленных объектов

• В gc.garbage список объектов с

циклическими ссылками и __del__.
Проходим по этому списку и разрываем
циклические ссылки. (gc.get_referrers)

• del
piątek, 27 września 13

gc.garbage[:]
Отладка
• gc.DEBUG_LEAK, gc.DEBUG_*
• Heapy (http://guppy-pe.sourceforge.net/)
• Meliae (https://launchpad.net/meliae)
• gdb-heap (https://fedorahosted.org/gdb-heap/)
piątek, 27 września 13
Альтернативы
• PyPy
• Отключить GC вообще и следить за деревом
объектов вручную

• Отключить но вызывать gc.collect() в
правильные моменты времени

piątek, 27 września 13
Спасибо
piątek, 27 września 13

Garbage collector and a bit of memory management

  • 1.
    Garbage collector and abit of memory management Cyril @notorca Lashkevich piątek, 27 września 13
  • 2.
    Модели управления памятью • Вручную •Подсчет ссылок • Garbage Collector piątek, 27 września 13
  • 3.
  • 4.
    Ручное управление • Переменныена стеке piątek, 27 września 13
  • 5.
    Ручное управление • Переменныена стеке • alloca piątek, 27 września 13
  • 6.
    Ручное управление • Переменныена стеке • alloca • Масивы переменной длинны (C99) piątek, 27 września 13
  • 7.
    Ручное управление • Переменныена стеке • alloca • Масивы переменной длинны (C99) • malloc/free piątek, 27 września 13
  • 8.
  • 9.
  • 10.
  • 11.
    Подсчет ссылок • retain(INCREF)/ release(DECREF) •autoreleasepool • weak piątek, 27 września 13
  • 12.
    DAG (directed acyclic graph) •Задача программиста не допускать циклов в графе объектов piątek, 27 września 13
  • 13.
    DAG (directed acyclic graph) •Задача программиста не допускать циклов в графе объектов piątek, 27 września 13
  • 14.
    DAG (directed acyclic graph) •Задача программиста не допускать циклов в графе объектов piątek, 27 września 13
  • 15.
    Что делать еслициклы нужны? piątek, 27 września 13
  • 16.
    Что делать еслициклы нужны? • Пример: граф с циклами piątek, 27 września 13
  • 17.
    Что делать еслициклы нужны? • Пример: граф с циклами • Приходится устранять циклы вручную piątek, 27 września 13
  • 18.
    Что делать еслициклы нужны? • Пример: граф с циклами • Приходится устранять циклы вручную piątek, 27 września 13
  • 19.
    Что делать еслициклы нужны? • Пример: граф с циклами • Приходится устранять циклы вручную piątek, 27 września 13
  • 20.
    Что делать еслициклы нужны? • Пример: граф с циклами • Приходится устранять циклы вручную piątek, 27 września 13
  • 21.
    Weak-ссылки • Не увеличивают счетчикссылок объекта • Автоматически зануляются при уничтожении объекта piątek, 27 września 13
  • 22.
    Python sys.getrefcount() import sys one= [] print 'At start :', sys.getrefcount(one) two = one print 'Second reference :', sys.getrefcount(one) del two print 'After del :', sys.getrefcount(one) piątek, 27 września 13
  • 23.
    Python sys.getrefcount() import sys one= [] print 'At start :', sys.getrefcount(one) two = one print 'Second reference :', sys.getrefcount(one) del two print 'After del :', sys.getrefcount(one) piątek, 27 września 13 At start : 2 Second reference : 3 After del : 2
  • 24.
    Анализ графа объектов •Функции для анализа в модуле gc • gc.get_referrers(*objs) • gc.get_referents(*objs) • Native-объекты должны предоставлять метод tp_traverse piątek, 27 września 13
  • 25.
    Модуль weakref • Слабыессылки с callback на удаление объекта • Proxy-объекты бросающие исключение при использовании удаленного объекта (not hashable!) • WeakValue и WeakKey словари • WeakSet (3.2) piątek, 27 września 13
  • 26.
    In [11]: obj= ExpensiveObject() In [12]: r = weakref.ref(obj) In [15]: print('obj:', obj) obj: <__main__.ExpensiveObject object at 0x108ea24d0> In [16]: print('ref:', r) ref: <weakref at 0x108eb62b8; to 'ExpensiveObject' at 0x108ea24d0> In [17]: print('r():', r()) r(): <__main__.ExpensiveObject object at 0x108ea24d0> In [18]: del obj Deleting Expencive object In [19]: print('r():', r()) r(): None piątek, 27 września 13
  • 27.
    Ограничения • Не всетипы могут быть weak: string, list, tuple... • Native-объекты должны реализовывать поддержку (через tp_weaklistoffset ) • Осторожно с weak словарями! piątek, 27 września 13
  • 28.
    Garbage Collector • Удаляетобъекты, недостижимые по ссылкам из корневого объекта но с ненулевым счетчиком ссылок piątek, 27 września 13
  • 29.
    GC в python •Запускается когда колличество созданых объектов поколения превышает количество удаленных на х (по умолчанию 700, 10, 10) • Либо вручную gc.collect() • Low memory, idle не инициируют сборку мусора • Может работать долго piątek, 27 września 13
  • 30.
  • 31.
    Generations and thresholds •3 "поколения" (списка) объектов: 0, piątek, 27 września 13 1, 2
  • 32.
    Generations and thresholds •3 "поколения" (списка) объектов: 0, 1, • Новые объекты попадают в 0 (не все) piątek, 27 września 13 2
  • 33.
    Generations and thresholds •3 "поколения" (списка) объектов: 0, 1, • Новые объекты попадают в 0 (не все) • Сборка мусора работает по поколениям piątek, 27 września 13 2
  • 34.
    Generations and thresholds •3 "поколения" (списка) объектов: 0, 1, • Новые объекты попадают в 0 (не все) • Сборка мусора работает по поколениям • Объекты пережившие сборку мусора переносятся в поколение +1 piątek, 27 września 13 2
  • 35.
    Generations and thresholds •3 "поколения" (списка) объектов: 0, 1, • Новые объекты попадают в 0 (не все) • Сборка мусора работает по поколениям • Объекты пережившие сборку мусора 2 переносятся в поколение +1 • Поколение 1 проверяется после threshold1 обработок поколения 0 piątek, 27 września 13
  • 36.
    Ограничения GC • Объектыс определенным __del__ не уничтожаются GC (он не знает в каком порядке их вызвать) • Native-объекты которые могут содержать ссылки должны правильно реализовывать tp_traverse piątek, 27 września 13
  • 37.
    Проблемы с __del__ •Может создать циклические ссылки с sys.exc_traceback и sys.last_traceback (их нужно явно занулить) • Исключения в __del__ игнорируются с выводом сообщения на stderr • Не вызывается при завершении программы piątek, 27 września 13
  • 38.
    Удаление неудаляемых объектов • Вызватьgc.collect() что бы явно запустить сборку мусора (вернет количество удаленных объектов • В gc.garbage список объектов с циклическими ссылками и __del__. Проходим по этому списку и разрываем циклические ссылки. (gc.get_referrers) • del piątek, 27 września 13 gc.garbage[:]
  • 39.
    Отладка • gc.DEBUG_LEAK, gc.DEBUG_* •Heapy (http://guppy-pe.sourceforge.net/) • Meliae (https://launchpad.net/meliae) • gdb-heap (https://fedorahosted.org/gdb-heap/) piątek, 27 września 13
  • 40.
    Альтернативы • PyPy • ОтключитьGC вообще и следить за деревом объектов вручную • Отключить но вызывать gc.collect() в правильные моменты времени piątek, 27 września 13
  • 41.