summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSjoerd Mullender <sjoerd@acm.org>1993-10-15 16:18:48 (GMT)
committerSjoerd Mullender <sjoerd@acm.org>1993-10-15 16:18:48 (GMT)
commit842d2ccdcd540399501a918b9724d2eaf5599f39 (patch)
treea62399047b129d4fe4f5db57a925fa7f135cabd2
parent21d335ed9ef6fbb16341809fe224b45a3f41243f (diff)
downloadcpython-842d2ccdcd540399501a918b9724d2eaf5599f39.zip
cpython-842d2ccdcd540399501a918b9724d2eaf5599f39.tar.gz
cpython-842d2ccdcd540399501a918b9724d2eaf5599f39.tar.bz2
intobject.c: Save references to small integers, so that they can be
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.
-rw-r--r--Objects/intobject.c37
-rw-r--r--Objects/object.c10
-rw-r--r--Objects/tupleobject.c55
3 files changed, 95 insertions, 7 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 816a411..6fcbe69 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -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;
}
diff --git a/Objects/object.c b/Objects/object.c
index a20b24d..bc0aeed 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -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
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index fae9386..bc68744 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -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