Pythonにおける整数オブジェクトの実装
Pythonの整数オブジェクトの実装を理解することは、Pythonのオブジェクトシステムを理解するのに役立ちます.ここ数日の読書内容をメモします.
PyIntobjectは、PyObjec_からなる構造体です.HEADとint ob_ivalの構成は、次のとおりです.
PyObject_HEADという構造体には、int refリファレンスカウンタ、struct_という2つのフィールドがあります.typeobject * ob_typeはタイプのポインタを表します.
Python整数タイプは小整数と大整数に分けられ、頻繁に使用される小整数については、参照カウント方式を採用し、同じ値で同じメモリを共有し、python初期化時に割り当てられます.
普通は-5~257で、自分で調整できます.この数に対して、完全にキャッシュされます.
大きな整数の場合、PyIntBlock構造を使用して単相リストを実現し、メモリをリンクし、使用するときはfree_リストから1枚取り出します.
もちろん、delが大きな整数オブジェクトの場合、メモリをシステムに返すのではなく、フリーチェーンテーブルに追加します.
最後に、整数オブジェクトの作成を見てみましょう.
PyIntobjectは、PyObjec_からなる構造体です.HEADとint ob_ivalの構成は、次のとおりです.
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
PyObject_HEADという構造体には、int refリファレンスカウンタ、struct_という2つのフィールドがあります.typeobject * ob_typeはタイプのポインタを表します.
Python整数タイプは小整数と大整数に分けられ、頻繁に使用される小整数については、参照カウント方式を採用し、同じ値で同じメモリを共有し、python初期化時に割り当てられます.
普通は-5~257で、自分で調整できます.この数に対して、完全にキャッシュされます.
#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS 257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS 5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
can be shared.
The integers that are saved are those in the range
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif
大きな整数の場合、PyIntBlock構造を使用して単相リストを実現し、メモリをリンクし、使用するときはfree_リストから1枚取り出します.
#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
#define N_INTOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))
struct _intblock {
struct _intblock *next;
PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;
static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;
もちろん、delが大きな整数オブジェクトの場合、メモリをシステムに返すのではなく、フリーチェーンテーブルに追加します.
最後に、整数オブジェクトの作成を見てみましょう.
PyObject *
PyInt_FromLong(long ival)
{
register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
v = small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);
#ifdef COUNT_ALLOCS
if (ival >= 0)
quick_int_allocs++;
else
quick_neg_int_allocs++;
#endif
return (PyObject *) v;
}
#endif
if (free_list == NULL) {
if ((free_list = fill_free_list()) == NULL)
return NULL;
}
/* Inline PyObject_New */
v = free_list;
free_list = (PyIntObject *)Py_TYPE(v);
PyObject_INIT(v, &PyInt_Type);
v->ob_ival = ival;
return (PyObject *) v;
}