Background
Original link: http://blog.csdn.net/ordeder/article/details/25343633
Python integer objects are immutable objects, what do you mean? For example, run the following Python statement
>>>a = 1023
>>>a = 1024
>>>b = A
>>>c = 1024
>>>d = 195
>>>e = 195
The integer object structure of Python is:
typedef struct {
Pyobject_head
Long Ob_ival;
} Pyintobject;
After the first command is run. The Python VM creates a pyintobject a, in which ob_ival=1023 records the value of the integer object, and name A refers to the object. That is the ob_refcnt=1 of a.
When you run the second statement. The Python VM also establishes a new Pyintobject B with a ob_ival value of 1024. And the name a dereference AA ob_refcnt-1 becomes 0 and the system recycles it. Name a refers to the ob_refcnt=1 of the object b,b;
Run the third statement, name B refers to the object referenced by name A, so B's ob_refcnt+1. That is 2.
Fourth statement: C refers to a different integer object than b
Fifth statement: D refers to a small integer object 195
The sixth statement: E and D refer to the same object. and small integer objects
P.S. The range of small integers is [-5,257]
The contents of the Pyintobject object Ob_ival in Python are immutable.
"Storage optimization for integer objects in Python" because the integer values recorded in Python are immutable, the value of name A is constantly changing. It involves the creation and destruction of multiple objects.
So Python has two optimizations for the integer object requisition space:
Optimization 1: Storage pool for Universal integer objects
Optimization 2: Building a special buffer for small integer objects
Pyintobject are divided into small integer objects [ -5~257) and large integer objects. The small integer object is initialized during the py startup process. This enables the caching of small integer objects, and small integer objects in the buffer are not destroyed during the py execution. A large integer object requires a program ape dynamic request, and the object determines whether to destroy (count 0) According to the OB_REFCNT reference count during execution.
Secondly. PY in order to optimize the application work for integer objects. Introduces the concept of a buffer pool for large integer objects. Why do I introduce a buffer pool? My understanding is: for the system. Alloc a Pyintobject object that requires a system call, the concept of an integer buffer pool is introduced in order to avoid invoking alloc each time the object is created.
"Small integer Buffering"
It's amazing to look at the name. The fact is that when the VM starts, the [ -5~257] integers are built into the corresponding integer objects beforehand.
These integers
The object is built in the same memory space as the: Universal Integer object's buffer pool.
Just the ob_refcnt of these small integer objects won't change.
And is always >0, so it will not be destroyed during VM execution. So it plays a role of Buffering.
"Buffer pool for universal integer objects"
In order to reduce the ALLOC system call request space, the memory pool one-time application of space is not a pyintobject size, but a pyintblock block as the size of the structure of space, each pyintblock block contains n pyintobject objects. The basic data structure for the memory pool is as follows:
#define BLOCK_SIZE / * 1K less typical malloc overhead */#define BHEAD_SIZE 8/ * enough for a 64-bit p Ointer */#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;
When the system is started. Pyintblock *block_list is empty, in the execution process, assuming the need to create an integer object, the system will first determine whether Block_list has spare space for creating objects, through Fill_free_list () The function obtains the available pyintobject from the buffer pool.
Assuming that the free_list has spare pyintobject available, you get the spare space directly in the buffer pool, you know.
Assuming there is no, the system will request a pyintblock by alloc to hang into Block_list, and at the same time divide the block into N_intobjects integer object pyintobject into Free_list.
1. Function implementation of fill_free_list ()
Static Pyintobject * Fill_free_list (void) { pyintobject *p, *q; /* Python ' s object allocator isn ' t appropriate for large blocks. */ P = (Pyintobject *) pymem_malloc (sizeof (Pyintblock)); if (p = = NULL) return (Pyintobject *) pyerr_nomemory (); ((Pyintblock *) p)->next = block_list; Block_list = (Pyintblock *) p; /* Link the Int objects together, from rear to front and then return the address of the last int object in the block. */< C9/>p = & ((Pyintblock *) p)->objects[0]; Q = p + n_intobjects; while (--q > P) py_type (q) = (struct _typeobject *) (Q-1);//[1] py_type (q) = NULL; return p + n_intobjects-1;}
Description [1]
PY uses Pyintobject->ob_type as a temporary next pointer to the free_list, using a pointer cast. Although the security principle of pointers has been compromised. However, >ob_type memory space is reused. is a good way! Depicts a universal integer buffer pool consisting of two pyintblock:
2. The remaining two build and delete integer object-related functions:
Build Intobjpyobject * 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) {//[1] if ((Free_list = Fill_free_list ()) = = null) return null; }/* Inline pyobject_new */v = free_list; [2] Free_list = (Pyintobject *) Py_type (v); Pyobject_init (V, &pyint_type); V->ob_ival = ival; Return (Pyobject *) v;} [1] The spare list of the buffer pool is empty, fill_free_list () to apply for a new pyintblock[2] (Pyintobject *) Py_type (v) equivalent to Pyintobject in Free_list in the next pointer. Delete intobjstatic void Int_dealloc (Pyintobject *v) {if (Pyint_checkexact (v)) {//[1] Py_type (v) = (struct _TYPEOB Ject *) Free_list; Free_list = v; } else//[2] Py_type (v)->tp_free ((Pyobject *) v);} [1] The decision assumes that the reference count of V is 1 (after this time the solution reference becomes 0). The Pyintobject space is increased to the spare queue of the buffer pool. to reuse [2] reference count >2 the object reference count minus 1
Python source code--the memory pool of an integer object (pyintobject)