Оптимизация экземпляров boost :: python :: object

Я недавно начал использовать Boost’s Python библиотека, чтобы обернуть части довольно большой библиотеки C ++.

Совершенно случайно я обнаружил, что каждый объект Python, созданный Boost Python, по крайней мере больше, чем размер списка Python.

Простые типы

С использованием noddy_NoddyType пример от C-Python API документы, Я могу довольно легко выставить новый экземпляр типа объекта, noddy_NoddyObject,

Используя сырой C-Python API, он настолько мал и прост, насколько может быть пользовательский объект Python:

>>> import noddy, sys

>>> print sys.getsizeof( noddy.Noddy )   # PyTypeObject size?
872
>>> print sys.getsizeof( noddy.Noddy() ) # PyObject size
16

И сравнить с базовым объектом: —

>>> print sys.getsizeof( object )
872
>>> print sys.getsizeof( object() )
16

Это, как и ожидалось, но как насчет того, когда я выставляю noddy_NoddyObject используя Boost Python?

>>> print sys.getsizeof( noddy.Noddy )
904
>>> print sys.getsizeof( noddy.Noddy() )
80

Чего-чего?!! Это не идеально … Экземпляры объектов в 5 раз больше, чем нужно!

(Это будет отличаться на не 64-битных машинах.)

На вики Boost Python есть какое-то объяснение для дополнительного раздувания: —

Потребление памяти

Как правило, обернутый объект C ++ с соответствующим объектом Python
размер:

  • класс нового стиля (производный от объекта в Python)
    экземпляр плюс
  • дополнительный размер, необходимый для разрешения данных переменной длины
    в случае
    , плюс
  • размер объекта C ++, плюс
  • размер указателя vtable, плюс указатель на объект C ++
    Экземпляр, плюс
  • ноль или более байтов заполнения, необходимого для обеспечения
    что держатель экземпляра правильно выровнен.

Вы можете увидеть это в boost/python/object/instance.hpp, Большинство объектов Python представлены instance<value_holder<T> >для некоторого класса C ++ T,

Но в частности нет никаких указаний ни относительно того, как уменьшить размер экземпляра, ни как использовать пользовательский PyTypeObject,

Типы последовательности

Итак, в instance.hpp, Вы можете видеть, что все boost::python::instanceиспользовать PyObject_VAR_HEAD в объявлении их базового класса. Это объяснило бы намного более близкое сходство в размере Boost Python-скомпилированного noddy_NoddyObjectк тому из питона list, или же numpy.array: —

>>> print sys.getsizeof( list )
872
>>> print sys.getsizeof( list() )
72
>>> print sys.getsizeof( numpy.array )
72
>>> print sys.getsizeof( numpy.array() )
80

(О, это интересно .. Если я не ошибаюсь, numpy.array это размер минимального PyObject экземпляр, который намного меньше, чем PyTypeObject, Интересно, какие там последствия ..)

Управление памятью

Помимо размера объекта, беспокойство, которое привело меня сюда, было одной из кучи транзакций. У меня есть базовый класс C ++, который состоит почти исключительно из функций, связанных с управлением памятью: он имеет new а также delete операторы; множество методов, связанных с подсчетом ссылок, и наследуется примерно сотней других классов C ++.

Прочитав один раз Документы C-Python API по определению новых типов, Я думал, что новый тип будет уместным здесь. Определив новый PyTypeObject структура и указав его членов (tp_allocи т. д.) для операторов и функций-членов класса C ++, я думал, что смогу заставить интерпретатор Python вызывать функции-члены C ++ напрямую. В этом случае производные классы не будут дублировать функциональность между типичными boost::python::object экземпляр и (уже управляемые) классы C ++.

С помощью bp::class_<> шаблоны, я полагал, что и код C ++, и код Python будут раздельно управлять памятью для экземпляров классов, что может показаться очень неэффективным.

Делать новый PyTypeObject

Используя новый PyTypeObjectЯ думаю, что все мои проблемы будут решены. Объем памяти простых объектов может быть намного меньше (я был бы очень рад, если бы я мог получить noddy_NoddyObject до 24 байт) и, похоже, будет гораздо больше гибкости в управлении этой памятью.

Итак, кто-нибудь еще когда-либо чувствовал необходимость определить новый PyTypeObject, отличается от значения по умолчанию для Boost Python? Как можно поступить об этом?

Переходя к большему базовому типу, похоже, что Boost теряет эффективность и гибкость. Потерять вес всегда тяжелее, чем набирать больше.

5

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]