Сериализация памяти Python

Мне было интересно, может ли кто-нибудь узнать ответ на следующее.

Я использую Python для создания дерева суффикса на основе символов. В дереве содержится более 11 миллионов узлов, которые подходят примерно к 3 ГБ памяти. Это уменьшилось с 7 ГБ, используя метод класса слотов, а не метод Dict .

Когда я сериализую дерево (используя самый высокий протокол), результирующий файл более чем в сто раз меньше.

Когда я загружаю маринованный файл, он снова потребляет 3 ГБ памяти. Откуда возникают эти дополнительные накладные расходы, связано ли это с тем, что Pythons обрабатывает ссылки на память на экземпляры классов?

Обновить

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

Я изначально хранил детей (максимум 30) в виде массива Numpy, затем пробовал версию аппаратного обеспечения ( ctypes.py_object*30 ), массив Python ( ArrayType ), а также словарь и типы Set.

Списки, казалось, делали лучше (используя guppy для профилирования памяти и __slots__['variable',...] ), но я все еще пытаюсь выкачать ее немного больше, если можно. Единственная проблема, с которой я столкнулся с массивами, – это заранее указать их размер, что вызывает некоторую избыточность в терминах узлов с одним ребенком, и у меня их довольно много. 😉

После того, как дерево построено, я намерен преобразовать его в вероятностное дерево со вторым проходом, но может быть, я могу сделать это по мере построения дерева. Поскольку время строительства не слишком важно в моем случае, array.array () звучит как нечто, что было бы полезно попробовать, спасибо за подсказку, действительно оценили.

Я дам вам знать, как это происходит.

2 Solutions collect form web for “Сериализация памяти Python”

Если вы попытаетесь рассортировать пустой список, вы получите:

 >>> s = StringIO() >>> pickle.dump([], s) >>> s.getvalue() '(l.' 

и аналогично '(d.' для пустого dict . Это три байта. Однако представление в списке в памяти списка содержит

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

На моей машине, которая имеет 64-битные указатели, sizeof заголовка списка Python составляет 40 байтов, так что это на порядок. Я предполагаю, что пустой dict будет иметь аналогичный размер.

Затем оба list и dict используют стратегию общего назначения для получения амортизированной производительности O (1) для своих основных операций, malloc вводит накладные расходы, есть атрибуты выравнивания, которые вы можете или не можете даже знать, и различные другие факторы, которые вы получаете второго порядка.

Подведение итогов: pickle – довольно хороший алгоритм сжатия для объектов Python 🙂

Вы строите свое дерево один раз, а затем используете его, не изменяя его дальше? В этом случае вам может потребоваться использовать отдельные структуры для динамической конструкции и статического использования.

Дикты и объекты очень хороши для динамической модификации, но они не очень эффективны в пространстве в сценарии только для чтения. Я не знаю точно, для чего вы используете дерево суффиксов, но вы можете позволить каждому узлу быть представленным 2-х кортежем отсортированного массива array.array ('c') и одинаково длинного кортежа субнодов (вместо этого вместо кортежа вектора, чтобы избежать обхода). Вы просматриваете дерево, используя модуль bisect для поиска в массиве. Индекс символа в массиве будет соответствовать подзоне в корте subdode. Таким образом, вы избегаете dicts, объектов и вектора.

Вы могли бы сделать что-то подобное во время процесса строительства, возможно, используя субнодный вектор, а не subnode-кортеж. Но это, конечно, сделает конструкцию медленнее, так как вложение новых узлов в отсортированный вектор равно O (N).

  • Django REST Framework Сериализация ForeignKey и ManyToManyFields
  • сохранение и загрузка объектов из файла с помощью jsonpickle
  • django-rest-framework: как мне сериализовать поле, которое уже содержит JSON?
  • AttributeError при использовании Django Rest Framework с сериализаторами
  • В Django loaddata он выдает ошибки для формата json, но правильно работает для формата yaml. Может ли кто-нибудь сказать мне, почему?
  • Динамически исключать или включать поле в сериализатор рамки Django REST
  • Почему Django Rest Framework препятствует проверке уровня модели?
  • Как получить дополнительный столбец в реляционной модели в сериализаторе Django-rest-framework?
  • Python - лучший язык программирования в мире.