Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 842d2cc

Browse files
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.
1 parent 21d335e commit 842d2cc

3 files changed

Lines changed: 95 additions & 7 deletions

File tree

Objects/intobject.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,42 @@ fill_free_list()
7575
}
7676

7777
static intobject *free_list = NULL;
78+
#ifndef NSMALLPOSINTS
79+
#define NSMALLPOSINTS 100
80+
#endif
81+
#ifndef NSMALLNEGINTS
82+
#define NSMALLNEGINTS 1
83+
#endif
84+
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
85+
/* References to small integers are saved in this array so that they
86+
can be shared.
87+
The integers that are saved are those in the range
88+
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
89+
*/
90+
static intobject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
91+
#endif
92+
#ifdef COUNT_ALLOCS
93+
int quick_int_allocs, quick_neg_int_allocs;
94+
#endif
7895

7996
object *
8097
newintobject(ival)
8198
long ival;
8299
{
83100
register intobject *v;
101+
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
102+
if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS &&
103+
(v = small_ints[ival + NSMALLNEGINTS]) != NULL) {
104+
INCREF(v);
105+
#ifdef COUNT_ALLOCS
106+
if (ival >= 0)
107+
quick_int_allocs++;
108+
else
109+
quick_neg_int_allocs++;
110+
#endif
111+
return (object *) v;
112+
}
113+
#endif
84114
if (free_list == NULL) {
85115
if ((free_list = fill_free_list()) == NULL)
86116
return NULL;
@@ -90,6 +120,13 @@ newintobject(ival)
90120
v->ob_type = &Inttype;
91121
v->ob_ival = ival;
92122
NEWREF(v);
123+
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
124+
if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
125+
/* save this one for a following allocation */
126+
INCREF(v);
127+
small_ints[ival + NSMALLNEGINTS] = v;
128+
}
129+
#endif
93130
return (object *) v;
94131
}
95132

Objects/object.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@ long ref_total;
3636

3737
#ifdef COUNT_ALLOCS
3838
static typeobject *type_list;
39-
39+
extern int tuple_zero_allocs, fast_tuple_allocs;
40+
extern int quick_int_allocs, quick_neg_int_allocs;
4041
void
4142
dump_counts()
4243
{
4344
typeobject *tp;
4445

4546
for (tp = type_list; tp; tp = tp->tp_next)
46-
printf("%s %d %d %d\n", tp->tp_name, tp->tp_alloc, tp->tp_free,
47+
printf("%s alloc'd: %d, freed: %d, max in use: %d\n",
48+
tp->tp_name, tp->tp_alloc, tp->tp_free,
4749
tp->tp_maxalloc);
50+
printf("fast tuple allocs: %d, empty: %d\n", fast_tuple_allocs,
51+
tuple_zero_allocs);
52+
printf("fast int allocs: pos: %d, neg: %d\n", quick_int_allocs,
53+
quick_neg_int_allocs);
4854
}
4955

5056
void

Objects/tupleobject.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2626

2727
#include "allobjects.h"
2828

29+
#ifndef MAXSAVESIZE
30+
#define MAXSAVESIZE 20
31+
#endif
32+
33+
#if MAXSAVESIZE > 0
34+
/* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
35+
tuple () of which at most one instance will be allocated.
36+
*/
37+
static tupleobject *free_list[MAXSAVESIZE];
38+
#endif
39+
#ifdef COUNT_ALLOCS
40+
int fast_tuple_allocs;
41+
int tuple_zero_allocs;
42+
#endif
43+
2944
object *
3045
newtupleobject(size)
3146
register int size;
@@ -36,15 +51,39 @@ newtupleobject(size)
3651
err_badcall();
3752
return NULL;
3853
}
39-
op = (tupleobject *)
40-
malloc(sizeof(tupleobject) + size * sizeof(object *));
41-
if (op == NULL)
42-
return err_nomem();
54+
#if MAXSAVESIZE > 0
55+
if (size == 0 && free_list[0]) {
56+
op = free_list[0];
57+
INCREF(op);
58+
#ifdef COUNT_ALLOCS
59+
tuple_zero_allocs++;
60+
#endif
61+
return (object *) op;
62+
}
63+
if (0 < size && size < MAXSAVESIZE && (op = free_list[size]) != NULL) {
64+
free_list[size] = (tupleobject *) op->ob_item[0];
65+
#ifdef COUNT_ALLOCS
66+
fast_tuple_allocs++;
67+
#endif
68+
} else
69+
#endif
70+
{
71+
op = (tupleobject *)
72+
malloc(sizeof(tupleobject) + size * sizeof(object *));
73+
if (op == NULL)
74+
return err_nomem();
75+
}
4376
op->ob_type = &Tupletype;
4477
op->ob_size = size;
4578
for (i = 0; i < size; i++)
4679
op->ob_item[i] = NULL;
4780
NEWREF(op);
81+
#if MAXSAVESIZE > 0
82+
if (size == 0) {
83+
free_list[0] = op;
84+
INCREF(op); /* extra INCREF so that this is never freed */
85+
}
86+
#endif
4887
return (object *) op;
4988
}
5089

@@ -113,7 +152,13 @@ tupledealloc(op)
113152
if (op->ob_item[i] != NULL)
114153
DECREF(op->ob_item[i]);
115154
}
116-
free((ANY *)op);
155+
#if MAXSAVESIZE > 0
156+
if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
157+
op->ob_item[0] = (object *) free_list[op->ob_size];
158+
free_list[op->ob_size] = op;
159+
} else
160+
#endif
161+
free((ANY *)op);
117162
}
118163

119164
static int

0 commit comments

Comments
 (0)