[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
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com