了解Python中大整数的内存分配
Python如何为大整数分配内存?
一个int
类型的大小的28 bytes
,当我不断增加的价值int
,在增量的大小增加4 bytes
。
-
为什么
28 bytes
最初要低至任何值1
? -
为什么增加
4 bytes
?
PS:我在x86_64(64位计算机)上运行Python 3.5.2。我正在寻找有关(3.0+)解释器如何在如此庞大的数量上工作的任何指针/资源/ PEP。
说明大小的代码:
>>> a=1
>>> print(a.__sizeof__())
28
>>> a=1024
>>> print(a.__sizeof__())
28
>>> a=1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024*1024*1024
>>> a
1152921504606846976
>>> print(a.__sizeof__())
36
-
为什么
28
字节的初始值低至1
?我相信@bgusach完全回答了这一点;Python使用
C
结构来表示Python世界中的对象,包括int
s的任何对象:struct _longobject { PyObject_VAR_HEAD digit ob_digit[1]; };
PyObject_VAR_HEAD
是一个宏,在展开时会在结构中添加另一个字段(该字段PyVarObject
专门用于具有某种长度概念的对象),并且ob_digits
是一个保存数字值的数组。锅炉板大小来自于结构,为小型
和 大型Python号码。为什么增加
4
字节?因为,当创建更大的数字时,大小(以字节为单位)是
sizeof(digit)
;的倍数。您可以看到,在_PyLong_New
其中使用以下命令longobject
执行新的内存分配PyObject_MALLOC
:/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) + sizeof(digit)*size. Previous incarnations of this code used sizeof(PyVarObject) instead of the offsetof, but this risks being incorrect in the presence of padding between the PyVarObject header and the digits. */ if (size > (Py_ssize_t)MAX_LONG_DIGITS) { PyErr_SetString(PyExc_OverflowError, "too many digits in integer"); return NULL; } result = PyObject_MALLOC(offsetof(PyLongObject, ob_digit) + size*sizeof(digit));
offsetof(PyLongObject, ob_digit)
是与保持其值无关的长对象的“模板”(以字节为单位)。digit
在头文件保持被定义struct _longobject
为typedef
为uint32
:typedef uint32_t digit;
并且
sizeof(uint32_t)
是4
字节。这是当size
参数to_PyLong_New
增大时您将看到的大小(以字节为单位)增加的数量。
当然,这就是
C
Python选择实现它的方式。这是一个实现细节,因此您不会在PEP中找到太多信息。如果您可以找到相应的线程:-),则python-
dev邮件列表将包含实现讨论。无论哪种方式,您都可能在其他流行的实现中发现不同的行为,因此请不要认为这是理所当然的。