我只是尝试了内存中python数据结构的大小。我写了以下代码片段:
import sys
lst1=[]
lst1.append(1)
lst2=[1]
print(sys.getsizeof(lst1), sys.getsizeof(lst2))
我在以下配置上测试了代码:
52 40
所以lst1有52个字节,lst2有40个字节。48 32
48 36
谁能向我解释为什么两个大小都不同,尽管它们都是包含1的列表?
在getsizeof函数的python文档中,我发现了以下内容:...adds an additional garbage collector overhead if the object is managed by the garbage collector.
在我的小示例中可能是这种情况吗?
这是一个更完整的交互式会议,它将帮助我解释发生了什么(Windows XP 32位上的Python 2.6,但这并不重要):
>>> import sys
>>> sys.getsizeof([])
36
>>> sys.getsizeof([1])
40
>>> lst = []
>>> lst.append(1)
>>> sys.getsizeof(lst)
52
>>>
请注意,空列表要比其中的空列表小一些[1]
。但是,添加元素后,它会变得更大。
原因是Objects/listobject.c
CPython源代码中的实现细节。
[]
创建空列表时,不会为元素分配空间-在中可以看到PyList_New
。36字节是32位计算机上列表数据结构本身所需的空间量。
[1]
创建具有单个元素的列表时,除了列表数据结构本身所需的内存外,还为一个元素分配了空间。同样,可以在中找到PyList_New
。鉴于size
作为参数,它计算:
nbytes = size * sizeof(PyObject *);
然后具有:
if (size <= 0)
op->ob_item = NULL;
else {
op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
if (op->ob_item == NULL) {
Py_DECREF(op);
return PyErr_NoMemory();
}
memset(op->ob_item, 0, nbytes);
}
Py_SIZE(op) = size;
op->allocated = size;
因此,我们看到有了size = 1
,分配了一个指针的空间。4个字节(在我的32位框中)。
呼叫append
空白清单时,会发生以下情况:
PyList_Append
来电 app1
app1
询问列表的大小(并得到0作为答案)app1
然后list_resize
以size+1
(在我们的例子中为1)进行呼叫list_resize
有一个有趣的分配策略,此注释从其来源进行了总结。这里是:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
/* check for integer overflow */
if (new_allocated > PY_SIZE_MAX - newsize) {
PyErr_NoMemory();
return -1;
} else {
new_allocated += newsize;
}
让我们看看如何达到在本文开头的会话中引用的数字。
因此,列表数据结构本身在32位上所需的大小为36个字节。对于单个元素,将为一个指针分配空间,因此这是4个额外的字节-总共40个字节。到目前为止还可以。
在app1
空白列表中调用list_resize
时,会使用调用size=1
。根据的过度分配算法list_resize
,1之后的下一个最大可用大小为4,因此将分配4个指针的位置。4 * 4 = 16个字节,36 + 16 = 52。
确实,一切都说得通:-)
问题内容: 如果我在python中有一个列表(或数组,字典…),它可能会超出可用的内存地址空间,(32位python)有哪些选项和相对速度?(除了不使列表变大之外)列表 可能 超出内存,但我无法事先知道。一旦开始超过75%,我将不再希望将该列表保留在内存中(或者无论如何都不会保留新项目),有没有办法在中途转换为基于文件的方法? 最佳(快进和快出)文件存储选项是什么? 只需要存储一个简单的数字列表。
问题内容: 我听过关于Java程序中一个字节占用的内存量的意见不一。 我知道您在一个Java字节中最多可以存储+127,并且文档说一个字节只有8位,但是在这里我被告知实际上它占用的内存量与int相同,因此仅一种有助于代码理解而不是效率的类型。 谁能解决这个问题,这将是实现特定的问题吗? 问题答案: 好的,已经进行了很多讨论,而没有很多代码:) 这是一个快速基准测试。谈到这种事情,通常会有一些警告-
问题内容: 我的磁盘上只有168MB的文件。这只是一个逗号分隔的单词,id的列表。该单词的长度可以为1-5个字符。有650万行。 我在python中创建了一个字典,将其加载到内存中,因此我可以针对该单词列表搜索传入的文本。当python将其加载到内存中时,它显示已使用的1.3 GB RAM空间。知道为什么吗? 假设我的word文件如下所示… 然后再加上650万。然后,我遍历该文件并创建一个字典(p
问题内容: 我正在尝试加载大于h2o中的内存大小的数据。 H2o 博客提到: 这是连接到的代码: 给 我试图将169 MB的csv加载到h2o中。 这引发了错误, 这表示内存不足错误。 问题:如果H2o承诺加载大于其内存容量的数据集(如上面的博客引文所述,交换到磁盘机制),这是加载数据的正确方法吗? 问题答案: 由于性能太差,默认情况下前一会默认禁用“交换到磁盘”。流血边缘(不是最新稳定的)具有启
我正在尝试在h2o中加载大于内存大小的数据。 H2o博客提到: 下面是连接到h2o 3.6.0.8的代码: 给 我试着把一个169 MB的csv加载到h2o中。 这抛出了一个错误, 这表示内存溢出错误。 问:如果H2opromise加载大于其内存容量的数据集(如上面的博客引述所说的交换到磁盘机制),这是加载数据的正确方法吗?
我一直试图从内部存储中删除所选项目的列表,但无法这样做。 它什么都不做。我该怎么改还是有什么更好的办法?任何帮助都将不胜感激。