优化boost :: python :: object实例

Ale*_*ach 5 c++ python numpy boost-python python-c-extension

我最近开始使用Boost的Python库来包装一个相当大的C++库的一部分.

很偶然,我发现Boost Python创建的每个Python对象至少比Python List的大小要大.

简单的类型

使用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
Run Code Online (Sandbox Code Playgroud)

并与基础对象进行比较: -

>>> print sys.getsizeof( object )
872
>>> print sys.getsizeof( object() )
16
Run Code Online (Sandbox Code Playgroud)

这是预期的,但是当我noddy_NoddyObject使用Boost Python 公开时呢?

>>> print sys.getsizeof( noddy.Noddy )
904
>>> print sys.getsizeof( noddy.Noddy() )
80
Run Code Online (Sandbox Code Playgroud)

说什么?!!那不太理想......对象实例比它们需要的大5倍!

(这在非64位计算机上会有所不同.)

在Boost Python维基上,有一些额外膨胀的解释: -

内存消耗

通常,带有相应Python对象的包装C++对象的大小为:

  • 一个新式的类(派生自Python中的'object')实例加
  • 所需的额外尺寸,以允许在该实例的可变长度数据,加
  • 加上C++对象的大小
  • vtable指针的大小,加上指向C++对象的实例持有者的指针
  • 需要零个或多个填充字节以确保实例持有者正确对齐.

你可以看到这个boost/python/object/instance.hpp.instance<value_holder<T> >对于某些C++类,大多数Python对象都表示为T.

但是,没有迹象表明如何减少实例大小,也没有如何使用自定义PyTypeObject.

序列类型

所以,instance.hpp你可以看到,所有boost::python::instance的使用PyObject_VAR_HEAD在其基类的声明.这可以解释的更接近的相似性在加速的大小Python的编译noddy_NoddyObject,到一个Python的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
Run Code Online (Sandbox Code Playgroud)

(哦,这很有趣..如果我没弄错的话,numpy.array是一个最小PyObject实例的大小,它比a小得多PyTypeObject.我想知道那里有什么含义......)

内存管理

除了对象大小之外,我在这里引起的关注是堆事务.我有一个C++基类,它几乎只包含与内存管理相关的功能:它有newdelete运算符; 大量与引用计数相关的方法,并由大约一百个其他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正在失去效率和灵活性.减肥总是比获得更多更痛苦.