mirror of https://github.com/python/cpython
Added some statistics code to dict and list object code. I wanted to test how a larger freelist affects the reusage of freed objects. Contrary to my gut feelings 80 objects is more than fine for small apps. I haven't profiled a large app yet.
This commit is contained in:
parent
9521f08b98
commit
b4ee4a16f4
|
@ -162,6 +162,22 @@ show_counts(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Debug statistic to compare allocations with reuse through the free list */
|
||||||
|
#undef SHOW_ALLOC_COUNT
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
static size_t count_alloc = 0;
|
||||||
|
static size_t count_reuse = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_alloc(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Dict allocations: %zd\n", count_alloc);
|
||||||
|
fprintf(stderr, "Dict reuse through freelist: %zd\n", count_reuse);
|
||||||
|
fprintf(stderr, "%.2f%% reuse rate\n\n",
|
||||||
|
(100.0*count_reuse/(count_alloc+count_reuse)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialization macros.
|
/* Initialization macros.
|
||||||
There are two ways to create a dict: PyDict_New() is the main C API
|
There are two ways to create a dict: PyDict_New() is the main C API
|
||||||
function, and the tp_new slot maps to dict_new(). In the latter case we
|
function, and the tp_new slot maps to dict_new(). In the latter case we
|
||||||
|
@ -199,6 +215,9 @@ PyDict_New(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
#ifdef SHOW_CONVERSION_COUNTS
|
#ifdef SHOW_CONVERSION_COUNTS
|
||||||
Py_AtExit(show_counts);
|
Py_AtExit(show_counts);
|
||||||
|
#endif
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
Py_AtExit(show_alloc);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (numfree) {
|
if (numfree) {
|
||||||
|
@ -212,11 +231,17 @@ PyDict_New(void)
|
||||||
assert (mp->ma_used == 0);
|
assert (mp->ma_used == 0);
|
||||||
assert (mp->ma_table == mp->ma_smalltable);
|
assert (mp->ma_table == mp->ma_smalltable);
|
||||||
assert (mp->ma_mask == PyDict_MINSIZE - 1);
|
assert (mp->ma_mask == PyDict_MINSIZE - 1);
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
count_reuse++;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
|
||||||
if (mp == NULL)
|
if (mp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
EMPTY_TO_MINSIZE(mp);
|
EMPTY_TO_MINSIZE(mp);
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
count_alloc++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
mp->ma_lookup = lookdict_string;
|
mp->ma_lookup = lookdict_string;
|
||||||
#ifdef SHOW_CONVERSION_COUNTS
|
#ifdef SHOW_CONVERSION_COUNTS
|
||||||
|
|
|
@ -63,6 +63,22 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Debug statistic to compare allocations with reuse through the free list */
|
||||||
|
#undef SHOW_ALLOC_COUNT
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
static size_t count_alloc = 0;
|
||||||
|
static size_t count_reuse = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_alloc(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "List allocations: %zd\n", count_alloc);
|
||||||
|
fprintf(stderr, "List reuse through freelist: %zd\n", count_reuse);
|
||||||
|
fprintf(stderr, "%.2f%% reuse rate\n\n",
|
||||||
|
(100.0*count_reuse/(count_alloc+count_reuse)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Empty list reuse scheme to save calls to malloc and free */
|
/* Empty list reuse scheme to save calls to malloc and free */
|
||||||
#ifndef PyList_MAXFREELIST
|
#ifndef PyList_MAXFREELIST
|
||||||
#define PyList_MAXFREELIST 80
|
#define PyList_MAXFREELIST 80
|
||||||
|
@ -88,6 +104,13 @@ PyList_New(Py_ssize_t size)
|
||||||
{
|
{
|
||||||
PyListObject *op;
|
PyListObject *op;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
static int initialized = 0;
|
||||||
|
if (!initialized) {
|
||||||
|
Py_AtExit(show_alloc);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
|
@ -101,10 +124,16 @@ PyList_New(Py_ssize_t size)
|
||||||
numfree--;
|
numfree--;
|
||||||
op = free_list[numfree];
|
op = free_list[numfree];
|
||||||
_Py_NewReference((PyObject *)op);
|
_Py_NewReference((PyObject *)op);
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
count_reuse++;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
op = PyObject_GC_New(PyListObject, &PyList_Type);
|
op = PyObject_GC_New(PyListObject, &PyList_Type);
|
||||||
if (op == NULL)
|
if (op == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#ifdef SHOW_ALLOC_COUNT
|
||||||
|
count_alloc++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
op->ob_item = NULL;
|
op->ob_item = NULL;
|
||||||
|
|
Loading…
Reference in New Issue