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分配巨大的内部结构?
发布于 2009-02-21 13:43:26
在32位系统上,您创建的8000000个列表中的每个列表将为列表对象本身分配20个字节,外加16个字节用于列表元素的向量。因此,您正在尝试分配至少(20+16) * 8000000 = 20168000000字节,大约20 GB。在最好的情况下,如果系统malloc只分配所请求的内存,这是最好的情况。
我计算了列表对象的大小,如下所示:
list结构本身中的2个指针(请参见listobject.h)
PyListObject对象的Py_ssize_t部分的一个PyObject_HEAD (请参见object.h)
Py_ssize_t Py_ssize_tPyObject_VAR_HEAD (也在Py_ssize_t中)列表元素的向量被稍微过度分配,以避免在每次追加时都必须调整它的大小-请参见listobject.c中的list_resize。大小有0,4,8,16,25,35,46,58,72,88,...因此,您的单元素列表将为4个元素分配空间。
您的数据结构是一个有点病态的示例,它为一个可变大小的列表对象付出了代价,却没有利用它-所有的列表都只有一个元素。您可以通过使用元组而不是列表来避免12字节的过度分配,但是为了进一步减少内存消耗,您必须使用使用较少对象的不同数据结构。很难说得更具体,因为我不知道你想要实现什么。
发布于 2009-02-21 10:47:02
我有点搞不懂你在问什么。在该代码示例中,任何内容都不应该被垃圾收集,因为您永远不会实际杀死任何引用。您在a中保存了对顶级列表的引用,并在其中添加了嵌套列表(每次迭代时在b中保存)。如果去掉'a =',那么你就得到了未引用的对象。
编辑:作为对第一部分的响应,是的,Python保存了一个对象列表,因此它可以知道要剔除什么。这就是全部问题吗?如果没有,请评论/编辑您的问题,我将尽我所能帮助您填补空白。
发布于 2009-02-21 11:20:33
您想要用
a = b = []和
b = b[0]声明?在Python语言中看到这样的语句肯定很奇怪,因为它们不会做您可能天真期望的事情:在这个示例中,a和b是同一列表的两个名称(想想C中的指针)。如果您正在进行大量这样的操作,很容易使垃圾收集器(以及您自己)感到困惑!因为你有很多奇怪的引用没有被正确的清除。
如果不知道为什么要做看起来像是在做的事情,就很难诊断出代码出了什么问题。当然,它暴露了一些解释器的怪癖...但我猜您正在以一种奇怪的方式处理您的问题,而一种更具Pythonic风格的方法可能会产生更好的结果。
https://stackoverflow.com/questions/572780
复制相似问题