整数对象的结构
整数对象是固定大小的Python对象,内部只有一个ob_ival
保存实际的整数值。
|
|
整数对象的缓存
为了最大限度的减少内存分配和垃圾回收,Python对整数对象设计了缓存。整数对象的缓存由两种类别构成:
- 小整数对象: 在Python启动时创建,永远不会回收
- 其他整数对象:创建时分配,回收时先缓存;在最高代的垃圾回收中整体回收
在Python启动时会创建一批默认值为[5, 257)的小整数对象,存储在small_ints
中。这些整数对象的生命周期为Python的生命周期,不会被回收。Python只所以这样处理是因此解释器内部会频繁用到这些小整数,如果每次都分配-回收-再分配显然效率不高,不如创建后一直保留用空间换时间。
|
|
可以通过id
命令查看小整数对象的特性。
|
|
通过上面的例子我们可以知道,其他整数对象使用的内存是不固定的,申请时分配释放时回收。当然,这个回收并不一定是返还给系统内存,整数对象系统本身会缓存一部分整数对象。下面通过整数对象系统的初始化揭露整数的缓存方案。
整数对象的初始化
当Python初始化时会调用_PyInt_Init
函数进行整数的初始化。
|
|
缓存会用到数据结构PyIntBlock
以及block_list
和free_list
链表。PyInBlock
用来一次申请多个整数对象的内存,然后再一个个用作PyIntObject
,并且通过域next
链接到block_list
链表上。free_list
中是空闲的PyIntObject
的链表。fill_free_list
初始化后的内存结构如下。
然后通过_PyInt_init
初始化为小整数,并将其指针存储到samll_ints
数组中加快查找。_PyInt_init
初始化后的内存结构如下。
我们可以看到整数对象通过PyIntBlock
和free_list
进行内存申请和缓存的。
整数对象的创建
当新创建一个整数对象时,先从free_list
中查找空闲的整数对象,如果有则直接使用;否则会重新分配PyIntBlock
结构并进行初始化。
|
|
创建一个新的整数257
之后的数据结构:
整数对象的回收
当整数对象的引用计数归零时则对其进行回收,由函数int_free
操作
|
|
可以看到被回收的整数对象被连接到free_list
链表中。这里有个问题,整数对象的内存什么时候才真正释放呢?
整数对象的释放
原来整数对象的真正释放是在最高代的GC
中进行,当GC
运行时会调用PyInt_ClearFreeList
进行整数对象内存的释放PyInt_ClearFreeList
对整个block_list
进行遍历,如果其中所有的整数对象的引用计数都为零,则释放整个block
。可见整数对象的内存是以PyIntBlock
为单位申请和释放的。
|
|
整数对象的操作符
整数对象定义了许多操作符,可以通过以下代码自行查看。
|
|
intobject.c源码注释
|
|