(Python学习2)整数对象

整数类型比较简单,定义如下(Python2.x中,在Python3.x中int与long合并)

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

整数在程序执行过程中创建销毁特别频繁,Python使用整数对象池(几乎所有对象都是)来避免内存的频繁申请释放。

分为小整数对象池、通用整数对象池。

1、整数对象池基础结构

#define BLOCK_SIZE  1000      // 内存块的大小
#define BHEAD_SIZE  8         // 容纳64位指针
#define N_INTOBJECTS    ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))   // 容纳整数对象的个数

typedef struct _intblock {
    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
}PyIntBlock;
 
static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;
如图所示,objects实质为N个整数对象的数组。

block_list通过单向列表维护整个对象池,free_list通过单向列表维护所有未使用内存。

(Python学习2)整数对象_第1张图片

2、通用整数对象池

创建通用整数对象池时,会使得objects中每个整数对象的ob_type指向前一个整数对象,从而形成单向列表。

在freelist指向的地方创建一个整数对象,然后free_list指向下一个空闲空间。当一个整数对象的引用计数为0时,该对象的ob_type指向freelist所指空间,然后freelist指向该处,从而模拟出该对象已被删除。

static void int_dealloc(PyIntObject *v)
{
    if (PyInt_CheckExact(v)) {
        v->ob_type = (struct _typeobject *)free_list;
        free_list = v;
    }
    else
        v->ob_type->tp_free((PyObject *)v);
}

多次创建删除后,对象的ob_types是跨PyIntBlock的,从而freelist也可在多个PyIntBlock之间来回跳动,不会出现内存泄漏等情况。

3、小整数对象池

小整数对象池保存了[-5, 100)之间的整数对象,在python开始运行时初始化,指针按照顺序存放于small_ints[]中。

#define NSMALLPOSINTS       100
#define NSMALLNEGINTS       5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

整体结构如下图所示

-----------------------------------------------------------------------------------------------------------------

运行时,先查看是否在小对象池中,有则直接使用;无则在通用对象池中新建。

小对象池中整数对象是唯一的,即 a=5 与 b=5 指向同一对象。

大对象池中整数对象不一定,a=1234 与 b=1234不一定指向同一对象,与创建方式有关。

你可能感兴趣的:((Python学习2)整数对象)