[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

Reply via email to