GAE有各种各样的限制,其中一个是最大可分配内存块的大小达1Mb(现在是10倍,但这不会改变问题).限制意味着不能在list()中放置更多的项目,因为CPython会尝试为元素指针分配连续的内存块.拥有巨大的list()可以被认为是糟糕的编程习惯,但即使程序本身没有创建庞大的结构,CPython也会在后台维护一些.
似乎CPython正在维护单个全局对象列表或其他东西.即具有许多小对象的应用程序倾向于分配越来越大的单个内存块.
第一个想法是gc,禁用它会稍微改变应用程序行为,但仍然会保留一些结构.
遇到问题的最简单的简短应用程序是:
a = b = [] number_of_lists = 8000000 for i in xrange(number_of_lists): b.append([]) b = b[0]
任何人都可以告诉我如何防止CPython在应用程序中有很多对象时分配巨大的内部结构?
在32位系统上,您创建的8000000个列表中的每个列表将为列表对象本身分配20个字节,为列表元素的向量分配16个字节.所以你试图分配至少(20 + 16)*8000000 = 20168000000字节,大约20 GB.这是最好的情况,如果系统malloc只分配与请求的内存完全相同的内存.
我按如下方式计算了列表对象的大小:
2 PyListObject
结构本身的指针(参见listobject.h)
1个指针和一个列表对象Py_ssize_t
的PyObject_HEAD
部分(参见object.h)
一个Py_ssize_t
用于PyObject_VAR_HEAD
(也在object.h)
列表元素的向量略微过度分配,以避免在每个追加时调整它的大小 - 请参阅listobject.c中的 list_resize .大小为0,4,8,16,25,35,46,58,72,88,......因此,您的单元素列表将为4个元素分配空间.
您的数据结构是一个有点病态的示例,在不使用它的情况下支付可变大小的列表对象的价格 - 您的所有列表只有一个元素.您可以通过使用元组而不是列表来避免12字节的分配,但为了进一步减少内存消耗,您将不得不使用使用较少对象的不同数据结构.由于我不知道你想要完成什么,因此很难具体化.