]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
intobject.c: Save references to small integers, so that they can be
authorSjoerd Mullender <sjoerd@acm.org>
Fri, 15 Oct 1993 16:18:48 +0000 (16:18 +0000)
committerSjoerd Mullender <sjoerd@acm.org>
Fri, 15 Oct 1993 16:18:48 +0000 (16:18 +0000)
shared.  The default is to save references to the integers in
the range -1..99.  The lower limit can be set by defining
NSMALLNEGINTS (absolute value of smallest integer to be saved)
and NSMALLPOSINTS (1 more than the largest integer to be
saved).
tupleobject.c: Save a reference to the empty tuple to be returned
whenever a tuple of size 0 is requested.  Tuples of size 1
upto, but not including, MAXSAVESIZE (default 20) are put in
free lists when deallocated.  When MAXSAVESIZE equals 1, only
share references to the empty tuple, when MAXSAVESIZE equals
0, don't include the code at all and revert to the old
behavior.
object.c: Print some more statistics when COUNT_ALLOCS is defined.

Objects/intobject.c
Objects/object.c
Objects/tupleobject.c

index 816a4112a2eb381631d463d46608a342777850b2..6fcbe6973381a96ff2b847537b51d300946cb705 100644 (file)
@@ -75,12 +75,42 @@ fill_free_list()
 }
 
 static intobject *free_list = NULL;
+#ifndef NSMALLPOSINTS
+#define NSMALLPOSINTS          100
+#endif
+#ifndef NSMALLNEGINTS
+#define NSMALLNEGINTS          1
+#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 intobject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
+#endif
+#ifdef COUNT_ALLOCS
+int quick_int_allocs, quick_neg_int_allocs;
+#endif
 
 object *
 newintobject(ival)
        long ival;
 {
        register intobject *v;
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0
+       if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS &&
+           (v = small_ints[ival + NSMALLNEGINTS]) != NULL) {
+               INCREF(v);
+#ifdef COUNT_ALLOCS
+               if (ival >= 0)
+                       quick_int_allocs++;
+               else
+                       quick_neg_int_allocs++;
+#endif
+               return (object *) v;
+       }
+#endif
        if (free_list == NULL) {
                if ((free_list = fill_free_list()) == NULL)
                        return NULL;
@@ -90,6 +120,13 @@ newintobject(ival)
        v->ob_type = &Inttype;
        v->ob_ival = ival;
        NEWREF(v);
+#if NSMALLNEGINTS + NSMALLPOSINTS > 0
+       if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
+               /* save this one for a following allocation */
+               INCREF(v);
+               small_ints[ival + NSMALLNEGINTS] = v;
+       }
+#endif
        return (object *) v;
 }
 
index a20b24d958f1bb4fcb617da095bb8c889aa2897b..bc0aeed295854e1adf3325d903edae90fb37d488 100644 (file)
@@ -36,15 +36,21 @@ long ref_total;
 
 #ifdef COUNT_ALLOCS
 static typeobject *type_list;
-
+extern int tuple_zero_allocs, fast_tuple_allocs;
+extern int quick_int_allocs, quick_neg_int_allocs;
 void
 dump_counts()
 {
        typeobject *tp;
 
        for (tp = type_list; tp; tp = tp->tp_next)
-               printf("%s %d %d %d\n", tp->tp_name, tp->tp_alloc, tp->tp_free,
+               printf("%s alloc'd: %d, freed: %d, max in use: %d\n",
+                      tp->tp_name, tp->tp_alloc, tp->tp_free,
                       tp->tp_maxalloc);
+       printf("fast tuple allocs: %d, empty: %d\n", fast_tuple_allocs,
+              tuple_zero_allocs);
+       printf("fast int allocs: pos: %d, neg: %d\n", quick_int_allocs,
+              quick_neg_int_allocs);
 }
 
 void
index fae9386968edf83fa985be218091255ce6a1691a..bc6874445d642848d8719850a49a62645ef436e4 100644 (file)
@@ -26,6 +26,21 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include "allobjects.h"
 
+#ifndef MAXSAVESIZE
+#define MAXSAVESIZE    20
+#endif
+
+#if MAXSAVESIZE > 0
+/* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
+   tuple () of which at most one instance will be allocated.
+*/
+static tupleobject *free_list[MAXSAVESIZE];
+#endif
+#ifdef COUNT_ALLOCS
+int fast_tuple_allocs;
+int tuple_zero_allocs;
+#endif
+
 object *
 newtupleobject(size)
        register int size;
@@ -36,15 +51,39 @@ newtupleobject(size)
                err_badcall();
                return NULL;
        }
-       op = (tupleobject *)
-               malloc(sizeof(tupleobject) + size * sizeof(object *));
-       if (op == NULL)
-               return err_nomem();
+#if MAXSAVESIZE > 0
+       if (size == 0 && free_list[0]) {
+               op = free_list[0];
+               INCREF(op);
+#ifdef COUNT_ALLOCS
+               tuple_zero_allocs++;
+#endif
+               return (object *) op;
+       }
+       if (0 < size && size < MAXSAVESIZE && (op = free_list[size]) != NULL) {
+               free_list[size] = (tupleobject *) op->ob_item[0];
+#ifdef COUNT_ALLOCS
+               fast_tuple_allocs++;
+#endif
+       } else
+#endif
+       {
+               op = (tupleobject *)
+                       malloc(sizeof(tupleobject) + size * sizeof(object *));
+               if (op == NULL)
+                       return err_nomem();
+       }
        op->ob_type = &Tupletype;
        op->ob_size = size;
        for (i = 0; i < size; i++)
                op->ob_item[i] = NULL;
        NEWREF(op);
+#if MAXSAVESIZE > 0
+       if (size == 0) {
+               free_list[0] = op;
+               INCREF(op);     /* extra INCREF so that this is never freed */
+       }
+#endif
        return (object *) op;
 }
 
@@ -113,7 +152,13 @@ tupledealloc(op)
                if (op->ob_item[i] != NULL)
                        DECREF(op->ob_item[i]);
        }
-       free((ANY *)op);
+#if MAXSAVESIZE > 0
+       if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
+               op->ob_item[0] = (object *) free_list[op->ob_size];
+               free_list[op->ob_size] = op;
+       } else
+#endif
+               free((ANY *)op);
 }
 
 static int