Программа на Python, использующая слишком много памяти - PullRequest
4 голосов
/ 14 ноября 2011

Я получил эти результаты от Heapy, но неясно, что именно они означают.

 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0 262539  59 36961284  48  36961284  48 dict (no owner)
     1  65536  15 34340864  45  71302148  93 dict of myobj.Container
     2  65536  15  2097152   3  73399300  96 myobj.Container

myobj - это класс с примерно 20 значениями True / False и 20 числовыми значениями (все из которых могут храниться в2 байта).

У меня есть массив из 256 * 256 из них.Я действительно не понимаю, почему они потребляют 35 или 70 МБ памяти.Я хотел бы довести его до 10 МБ, если это возможно.

Большая часть данных внутри объекта организована в словари для облегчения доступа.Сами словари не меняются и довольно бессмысленны.Могут ли они привести к значительным накладным расходам?

Было бы полезно упаковать все данные в 1 число с помощью побитовых операторов?Я должен иметь возможность хранить все данные объекта в 32 или 64 байта.Я надеялся, что компилятор будет делать такие вещи автоматически, как и другие языки, но, похоже, он делает противоположное.

Класс наследует объект встроенного типа только по причине использования декораторов.Может ли это привести к значительным накладным расходам?

Также любопытно, что означает «dict (без владельца)» и что он потребляет в другой половине памяти.

Редактировать: sys.getsizeof (myobj.Container)действительно сообщает 450 байт!Это безумие.Я использовал только словари, потому что мне нужен доступ к данным на основе индекса.Насколько мне известно, компилятор должен избавиться от структур и получить прямой доступ к значениям.Есть ли лучший способ сделать это?(Я не думаю, что списки - это ответ)

1 Ответ

6 голосов
/ 14 ноября 2011

Python не устраняет накладные расходы на подобные структуры.Сожалею.Его динамическая природа затрудняет такие оптимизации компилятора.Но тогда я не знаю ни одного языка, который бы устранял накладные расходы, связанные с хранением вещей в словарях.

dict (без владельца), вероятно, включает в себя все словари, которые вы создаете внутри своего объекта.Они помечены как не имеющие владельца, поскольку они не являются словарями для экземпляров объектов.

Что вы можете сделать:

Используйте __slots__, если вы добавите __slots__ = ('the','names','of','fields') в качестве атрибута класса, python будет использовать более эффективную реализацию класса.Это избавит от словаря, используемого для хранения атрибутов.

Если ваши словари могут быть переписаны для использования списков, которые могли бы улучшить ситуацию.Списки более эффективны по памяти, чем словари.

Для максимальной эффективности вы должны переработать свою систему, чтобы использовать массивы.Каждый атрибут в вашем классе станет массивом размером 256 * 256.Каждый элемент будет храниться очень эффективно в этом случае.

Кроме того, вы можете оформить заказ PyPy.Он предоставляет альтернативную реализацию Python с JIT, а также различные оптимизации времени / пространства, которые могут помочь.

sys.getsizeof не сообщает, о чем вы думаете, что сообщает.sys.getsizeof(myobj.Container) сообщает размер объекта класса, а не размер фактических объектов контейнера.Вы хотите sys.getsizeof(myobj.Container()) или подобное.Даже это не точно, потому что оно не включает ничего кроме базового объекта.Он не учитывает словарь, содержащий атрибуты.Он сообщит только размер третьей строки в вашем отчете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...