Upgrade to Pro — share decks privately, control downloads, hide ads and more …

На что уходит память

На что уходит память

PyCon RU 2014
Доклад о проблеме потребления памяти приложений на Python - как понять что происходит, и что делать, когда оно больше чем нам хотелось бы. Сначала мы посмотрим, как вообще Python работает с памятью внутри, как он взаимодействует с ОС, может ли он отдавать память. Затем рассмотрим инструменты для анализа потребления памяти, и научимся интерпретировать их результат. Разберем типичные ошибки, которые приводят к излишнему потреблению памяти, рассмотрим некоторые приемы, которые могут позволить его уменьшить даже при отсутствии явных ляпов. В отличие от темы анализа производительности, на тему анализа потребления памяти на удивление мало материала, в основном только ответы на stackoverflow, поэтому хочется попробовать систематизировать то, что удалось узнать.

Konstantin Lopuhin

June 02, 2014
Tweet

More Decks by Konstantin Lopuhin

Other Decks in Programming

Transcript

  1. . . Проблема Теория Инструменты Решения Ограничение размера задачи Объем

    памяти может ограничить максимальный размер решаемой задачи Изменить алгоритм так, чтобы не все держать в памяти, часто сложно . . . 6
  2. . . Проблема Теория Инструменты Решения Делаем ненужную работу Тратим

    лишнюю память и: не в лезаем влезаем в кэш процессовра делаем лишнюю работы по выделению и сборке памяти . . . 7
  3. . . Проблема Теория Инструменты Решения I/O bound? Часто можно

    превратить I/O bound задачу в CPU или Memory bound, и увеличить производительность . . . 8
  4. . . Проблема Теория Инструменты Решения Ограничение числа процессов Хотим

    использовать все ядра сервера Типичный сервер: 8-256 Гб памяти 4-128 ядер, 1-2 процесса на ядро 0.5-5 Гб памяти на процесс . . . 10
  5. . . Проблема Теория Инструменты Решения Что такое память Один

    из основных ресурсов В ней храняться текущие данные программы, она быстра и конечна Скорость доступа: L1: 0.5 ns, RAM: 100 ns, SSD: 150 000 ns . . . 11
  6. . . Проблема Теория Инструменты Решения Что с ней происходит

    Выделение (плюс взаимодействие с ОС) Чтение/запись Освобождение (сборщик мусора - GC) . . . 12
  7. . . Проблема Теория Инструменты Решения Как она используется class

    Point(object): def __init__(self, x, y, vx, vy): self.x = x self.y = y self.vx = vx self.vy = vy . . . 13
  8. . . Проблема Теория Инструменты Решения Сборка мусора освобождение объектов,

    к которым у нас уже нет доступа бесконечная память - сборщик не был бы нужен/заметен Пример: s = 0.0 for _ in xrange(10000000): s = s + 0.34 . . . 16
  9. . . Проблема Теория Инструменты Решения Сборка мусора: CPython reference

    coun ng: если на объект нет ссылок, то память можно освободить но нужно уметь собирать и отдельно висящие циклы только если в циклах нет объектов с __del__ (см. gc.garbage) . . . 17
  10. . . Проблема Теория Инструменты Решения Циклы: пример class Node:

    def __init__(self, parent=None): self.parent = parent self.children = [] a = Node() a.children.append(Node(parent=a)) a = 1 . . . 18
  11. . . Проблема Теория Инструменты Решения Циклы: __del__ class Node:

    def __init__(self, parent=None): self.parent = parent self.children = [] def __del__(self): pass a = Node(); a.children.append(Node(parent=a)) a = 1 . . . 19
  12. . . Проблема Теория Инструменты Решения Циклы: __del__ class Node:

    def __init__(self, parent=None): self.parent = parent self.children = [] def __del__(self): pass a = Node(); a.children.append(Node(parent=a)) a = 1 >>> gc.collect(); gc.garbage [<__main__.Node instance at 0x10a0dd5f0>, <__main__.Node instance at 0x10a0dd680>] . . . 20
  13. . . Проблема Теория Инструменты Решения Освобождение памяти ” Improving

    Python's Memory Allocator“ Evan Jones http://www.evanjones.ca/memoryallocator/ . . . 27
  14. . . Проблема Теория Инструменты Решения Инструменты Сколько памяти используется?

    Какие объекты занимают память? Почему они занимают память? . . . 29
  15. . . Проблема Теория Инструменты Решения Статистика ОС включает память

    C exten ons включает shared libraries дополнительная информация: vmmap, pmap -d import resource resource.getrusage(resource.RUSAGE_SELF).ru_maxrss . . . 30
  16. . . Проблема Теория Инструменты Решения Статистика ОС starting vlist_blocker

    ... finished vlist_blocker in 11.8649010658 s vlist_blocker: memory before: 32 440 k after: 412 016 k delta: 379 576 k . . . 31
  17. . . Проблема Теория Инструменты Решения heapy CPython 2.x overhead:

    нет (не считая времени на анализ) анализ используемой памяти сложно понять причину/источник . . . 32
  18. . . Проблема Теория Инструменты Решения heapy from guppy import

    hpy hp = hpy() hp.setrelheap() ... ... h = hp.heap() print h . . . 33
  19. . . Проблема Теория Инструменты Решения heapy 8343695 objects. Total

    size = 401971888 bytes. Index Count % Size % Cumulative % Kind (class / dict o 0 3337416 40 160M 40 160M 40 datetime.datetime 1 1668744 20 146M 37 307M 76 tuple 2 3336983 40 80M 20 387M 96 int 3 25 0 14M 4 401M 100 list 4 144 0 56K 0 401M 100 unicode 5 147 0 52K 0 401M 100 dict (no owner) ... . . . 34
  20. . . Проблема Теория Инструменты Решения heapy (Pdb) print h[1].byid

    1668748 <tuple> objects. Total size = 146849176 bytes. Index Size % Cumulative % Address*Length 0 88 0.0 88 0.0 0x10c141050*4 ... 9 88 0.0 88 0.0 0x10c141368*4 <1668738 more rows. Type e.g. '_.more' to view.> (Pdb) print h[1].byid[0].theone (108, 108, datetime.datetime(1, 1, 1, 0, 0), datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)) . . . 35
  21. . . Проблема Теория Инструменты Решения tracemalloc CPython 3.4 (есть

    порт для 2.7) overhead: ~2x и память и время отслеживание выделения памяти с точностью до строчки и traceback но как и с heapy, нужно ” поймать момент“ . . . 36
  22. . . Проблема Теория Инструменты Решения tracemalloc [ Top 10

    ] django/db/utils.py:106: size=344 MiB, count=8343028, average=43 B documents/utils.py:47: size=13.3 MiB, count=1, average=13.3 MiB <frozen importlib._bootstrap>:656: size=59.7 KiB, count=520, average=118 B django/db/backends/postgresql_psycopg2/operations.py:21 size=27.6 KiB, count=77, average=367 B ... . . . 37
  23. . . Проблема Теория Инструменты Решения Утечка 44 | values

    = [] 45 | for d in _blocks_iterator( 46 | blocks, vlist, field_name, model, log): 47 | values.append(d) 48 | yield d . . . 38
  24. . . Проблема Теория Инструменты Решения tracemalloc [ Top 10

    ] django/db/utils.py:106: size=160 KiB, count=2050, average=80 B <frozen importlib._bootstrap>:656: size=59.1 KiB, count=515, average=118 B django/db/backends/postgresql_psycopg2/operations.py:21 size=56.2 KiB, count=176, average=327 B django/db/backends/util.py:74: size=39.0 KiB, count=184, average=217 B django/db/backends/util.py:76: size=10.9 KiB, count=177, average=63 B . . . 39
  25. . . Проблема Теория Инструменты Решения Оптимизации: объекты class Point(object):

    def __init__(self, x, y, vx, vy): self.x = x self.y = y self.vx = vx self.vy = vy points = [Point(x=random(), y=random(), vx=random(), vy=random()) for _ in xrange(n)] . . . 41
  26. . . Проблема Теория Инструменты Решения __slots__ class Point(object): __slots__

    = ['x', 'y', 'vx', 'vy'] def __init__(self, x, y, vx, vy): self.x = x self.y = y self.vx = vx self.vy = vy . . . 43
  27. . . Проблема Теория Инструменты Решения struct class Point(object): __slots__

    = ['_data'] def __init__(self, x, y, vx, vy): self._data = struct.pack( '=dddd', x, y, vx, vy) @property def x(self): return struct.unpack( '=dddd', self._data)[0] . . . 46
  28. . . Проблема Теория Инструменты Решения cffi from cffi import

    FFI ffi = FFI() ffi.cdef(""" typedef struct { double x, y, vx, vy; } Point; """) points = ffi.new("Point[]", 10000000) . . . 47
  29. . . Проблема Теория Инструменты Решения Общая память mmap: https://docs.python.org/2/library/mmap.html

    mul processing: https: //docs.python.org/2/library/multiprocessing.html# sharing-state-between-processes http://stackoverflow.com/a/5550156/217088 . . . 49
  30. . . Проблема Теория Инструменты Решения Архитектурные решения вынос жадных

    до памяти операций в отдельный процесс (mul processing, Celery, ..., отдельный сервис) вынос общей памяти в отдельный процесс/БД (redis, memcached, ..., отдельный сервис) . . . 50
  31. . . Проблема Теория Инструменты Решения Ссылки: внутренности CPython Improving

    Python's Memory Allocator: http://www.evanjones.ca/memoryallocator/ Stepping Through CPython: http://www.youtube.com/watch?v=XGF3Qu4dUqk gc: https://docs.python.org/2/library/gc.html Why Python is Slow: Looking Under the Hood: http://jakevdp.github.io/blog/2014/05/09/ why-python-is-slow/ Python’s Innards: http://tech.blog.aknin.name/ category/my-projects/pythons-innards/ . . . 52
  32. . . Проблема Теория Инструменты Решения Ссылки: оптимизации в PyPy

    объекты: http://morepypy.blogspot.ru/2010/11/ efficiently-implementing-python-objects.html списки: http://morepypy.blogspot.ru/2011/10/ more-compact-lists-with-list-strategies.html . . . 53
  33. . . Проблема Теория Инструменты Решения Ссылки: инструменты Heapy: http://guppy-pe.sourceforge.net/

    http: //smira.ru/wp-content/uploads/2011/08/heapy.html Meliae: http://jam-bazaar.blogspot.ru/2009/11/ memory-debugging-with-meliae.html http://jam-bazaar.blogspot.ru/2010/08/ step-by-step-meliae.html . . . 54
  34. . . Проблема Теория Инструменты Решения Ссылки: tracemalloc Документация: https:

    //docs.python.org/3/library/tracemalloc.html PEP: http://legacy.python.org/dev/peps/pep-0454/ . . . 55