[EMAIL PROTECTED] schrieb: > Wouldn't use of obmalloc offset much of that? Before obmalloc was > available, the int free list was a huge win. Is it likely to be such a huge > win today?
I have now some numbers. For the attached t.py, the unmodified svn python gives Test 1 3.25420880318 Test 2 1.86433696747 and the one with the attached patch gives Test 1 3.45080399513 Test 2 2.09729003906 So there apparently is a performance drop on int allocations of about 5-10%. On this machine (P4 3.2GHz) I could not find any difference in pystones from this patch. Notice that this test case is extremely focused on measuring int allocation (I just noticed I should have omitted the for loop in the second case, though). Regards, Martin
import time s = time.time() i = 0 while i < 10000000: i+=1 print "Test 1",time.time()-s s = time.time() i = 0 for i in range(10000000): pass print "Test 2",time.time()-s
Index: Objects/intobject.c =================================================================== --- Objects/intobject.c (Revision 51320) +++ Objects/intobject.c (Arbeitskopie) @@ -13,54 +13,8 @@ /* Integers are quite normal objects, to make object handling uniform. (Using odd pointers to represent integers would save much space but require extra checks for this special case throughout the code.) - Since a typical Python program spends much of its time allocating - and deallocating integers, these operations should be very fast. - Therefore we use a dedicated allocation scheme with a much lower - overhead (in space and time) than straight malloc(): a simple - dedicated free list, filled when necessary with memory from malloc(). - - block_list is a singly-linked list of all PyIntBlocks ever allocated, - linked via their next members. PyIntBlocks are never returned to the - system before shutdown (PyInt_Fini). - - free_list is a singly-linked list of available PyIntObjects, linked - via abuse of their ob_type members. */ -#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; - -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, then return - the address of the last int object in the block. */ - p = &((PyIntBlock *)p)->objects[0]; - q = p + N_INTOBJECTS; - while (--q > p) - q->ob_type = (struct _typeobject *)(q-1); - q->ob_type = NULL; - return p + N_INTOBJECTS - 1; -} - #ifndef NSMALLPOSINTS #define NSMALLPOSINTS 257 #endif @@ -96,14 +50,9 @@ 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 *)v->ob_type; - PyObject_INIT(v, &PyInt_Type); + v = PyObject_NEW(PyIntObject, &PyInt_Type); + if (v == NULL) + return NULL; v->ob_ival = ival; return (PyObject *) v; } @@ -127,19 +76,13 @@ 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); + v->ob_type->tp_free((PyObject *)v); } static void int_free(PyIntObject *v) { - v->ob_type = (struct _typeobject *)free_list; - free_list = v; + PyObject_Del(v); } long @@ -1138,12 +1081,8 @@ int ival; #if NSMALLNEGINTS + NSMALLPOSINTS > 0 for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) { - if (!free_list && (free_list = fill_free_list()) == NULL) - return 0; - /* PyObject_New is inlined */ - v = free_list; - free_list = (PyIntObject *)v->ob_type; - PyObject_INIT(v, &PyInt_Type); + v = PyObject_NEW(PyIntObject, &PyInt_Type); + if (!v) return 0; v->ob_ival = ival; small_ints[ival + NSMALLNEGINTS] = v; } @@ -1154,14 +1093,8 @@ void PyInt_Fini(void) { - PyIntObject *p; - PyIntBlock *list, *next; - int i; - unsigned int ctr; - int bc, bf; /* block count, number of freed blocks */ - int irem, isum; /* remaining unfreed ints per block, total */ - #if NSMALLNEGINTS + NSMALLPOSINTS > 0 + int i; PyIntObject **q; i = NSMALLNEGINTS + NSMALLPOSINTS; @@ -1171,82 +1104,4 @@ *q++ = NULL; } #endif - bc = 0; - bf = 0; - isum = 0; - list = block_list; - block_list = NULL; - free_list = NULL; - while (list != NULL) { - bc++; - irem = 0; - for (ctr = 0, p = &list->objects[0]; - ctr < N_INTOBJECTS; - ctr++, p++) { - if (PyInt_CheckExact(p) && p->ob_refcnt != 0) - irem++; - } - next = list->next; - if (irem) { - list->next = block_list; - block_list = list; - for (ctr = 0, p = &list->objects[0]; - ctr < N_INTOBJECTS; - ctr++, p++) { - if (!PyInt_CheckExact(p) || - p->ob_refcnt == 0) { - p->ob_type = (struct _typeobject *) - free_list; - free_list = p; - } -#if NSMALLNEGINTS + NSMALLPOSINTS > 0 - else if (-NSMALLNEGINTS <= p->ob_ival && - p->ob_ival < NSMALLPOSINTS && - small_ints[p->ob_ival + - NSMALLNEGINTS] == NULL) { - Py_INCREF(p); - small_ints[p->ob_ival + - NSMALLNEGINTS] = p; - } -#endif - } - } - else { - PyMem_FREE(list); - bf++; - } - isum += irem; - list = next; - } - if (!Py_VerboseFlag) - return; - fprintf(stderr, "# cleanup ints"); - if (!isum) { - fprintf(stderr, "\n"); - } - else { - fprintf(stderr, - ": %d unfreed int%s in %d out of %d block%s\n", - isum, isum == 1 ? "" : "s", - bc - bf, bc, bc == 1 ? "" : "s"); - } - if (Py_VerboseFlag > 1) { - list = block_list; - while (list != NULL) { - for (ctr = 0, p = &list->objects[0]; - ctr < N_INTOBJECTS; - ctr++, p++) { - if (PyInt_CheckExact(p) && p->ob_refcnt != 0) - /* XXX(twouters) cast refcount to - long until %zd is universally - available - */ - fprintf(stderr, - "# <int at %p, refcnt=%ld, val=%ld>\n", - p, (long)p->ob_refcnt, - p->ob_ival); - } - list = list->next; - } - } }
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com