Kaydet (Commit) 2fe77060 authored tarafından Gregory P. Smith's avatar Gregory P. Smith

- Issue #2862: Make int and float freelist management consistent with other

  freelists.  Changes their CompactFreeList apis into ClearFreeList apis and
  calls them via gc.collect().
üst 17f2e4ac
......@@ -86,10 +86,9 @@ Floating Point Objects
.. versionadded:: 2.6
.. cfunction:: void PyFloat_CompactFreeList(size_t *bc, size_t *bf, size_t *sum)
.. cfunction:: int PyFloat_ClearFreeList(void)
Compact the float free list. *bc* is the number of allocated blocks before
blocks are freed, *bf* is the number of freed blocks and *sum* is the number
of remaining objects in the blocks.
Clear the float free list. Return the number of items that could not
be freed.
.. versionadded:: 2.6
......@@ -122,10 +122,9 @@ Plain Integer Objects
(:const:`LONG_MAX`, as defined in the system header files).
.. cfunction:: void PyInt_CompactFreeList(size_t *bc, size_t *bf, size_t *sum)
.. cfunction:: int PyInt_ClearFreeList(void)
Compact the integer free list. *bc* is the number of allocated blocks before
blocks are freed, *bf* is the number of freed blocks and *sum* is the number
of remaining objects in the blocks.
Clear the integer free list. Return the number of items that could not
be freed.
.. versionadded:: 2.6
......@@ -47,6 +47,12 @@ The :mod:`gc` module provides the following functions:
.. versionchanged:: 2.5
The optional *generation* argument was added.
.. versionchanged:: 2.6
The free lists maintained for a number of builtin types are cleared
whenever a full collection or collection of the highest generation (2)
is run. Not all items in some free lists may be freed due to the
particular implementation, in particular :class:`int` and :class:`float`.
.. function:: set_debug(flags)
......
......@@ -58,22 +58,6 @@ always available.
A string containing the copyright pertaining to the Python interpreter.
.. function:: _compact_freelists()
Compact the free lists of integers and floats by deallocating unused blocks.
It can reduce the memory usage of the Python process several tenth of
thousands of integers or floats have been allocated at once.
The return value is a tuple of tuples each containing three elements,
amount of used objects, total block count before the blocks are deallocated
and amount of freed blocks. The first tuple refers to ints, the second to
floats.
This function should be used for specialized purposes only.
.. versionadded:: 2.6
.. function:: _clear_type_cache()
Clear the internal type cache. The type cache is used to speed up attribute
......
......@@ -113,7 +113,7 @@ PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le);
PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
/* free list api */
PyAPI_FUNC(void) PyFloat_CompactFreeList(size_t *, size_t *, size_t *);
PyAPI_FUNC(int) PyFloat_ClearFreeList(void);
/* Format the object based on the format_spec, as defined in PEP 3101
(Advanced String Formatting). */
......
......@@ -60,7 +60,7 @@ PyAPI_FUNC(unsigned long) PyOS_strtoul(char *, char **, int);
PyAPI_FUNC(long) PyOS_strtol(char *, char **, int);
/* free list api */
PyAPI_FUNC(void) PyInt_CompactFreeList(size_t *, size_t *, size_t *);
PyAPI_FUNC(int) PyInt_ClearFreeList(void);
/* Convert an integer to the given base. Returns a string.
If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'.
......
......@@ -29,6 +29,10 @@ Core and Builtins
would not cause a syntax error. This was regression from 2.4 caused by the
switch to the new compiler.
- Issue #2862: Make int and float freelist management consistent with other
freelists. Changes their CompactFreeList apis into ClearFreeList apis and
calls them via gc.collect().
Library
-------
......
......@@ -736,6 +736,8 @@ clear_freelists(void)
(void)PyCFunction_ClearFreeList();
(void)PyTuple_ClearFreeList();
(void)PyUnicode_ClearFreeList();
(void)PyInt_ClearFreeList();
(void)PyFloat_ClearFreeList();
}
/* This is the main function. Read this to understand how the
......
......@@ -1608,30 +1608,28 @@ _PyFloat_Init(void)
PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc);
}
void
PyFloat_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum)
int
PyFloat_ClearFreeList(void)
{
PyFloatObject *p;
PyFloatBlock *list, *next;
unsigned i;
size_t bc = 0, bf = 0; /* block count, number of freed blocks */
size_t fsum = 0; /* total unfreed ints */
int frem; /* remaining unfreed ints per block */
int i;
int u; /* remaining unfreed ints per block */
int freelist_size = 0;
list = block_list;
block_list = NULL;
free_list = NULL;
while (list != NULL) {
bc++;
frem = 0;
u = 0;
for (i = 0, p = &list->objects[0];
i < N_FLOATOBJECTS;
i++, p++) {
if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0)
frem++;
u++;
}
next = list->next;
if (frem) {
if (u) {
list->next = block_list;
block_list = list;
for (i = 0, p = &list->objects[0];
......@@ -1646,15 +1644,12 @@ PyFloat_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum)
}
}
else {
PyMem_FREE(list); /* XXX PyObject_FREE ??? */
bf++;
PyMem_FREE(list);
}
fsum += frem;
freelist_size += u;
list = next;
}
*pbc = bc;
*pbf = bf;
*bsum = fsum;
return freelist_size;
}
void
......@@ -1662,25 +1657,21 @@ PyFloat_Fini(void)
{
PyFloatObject *p;
PyFloatBlock *list;
unsigned i;
size_t bc, bf; /* block count, number of freed blocks */
size_t fsum; /* total unfreed floats per block */
int i;
int u; /* total unfreed floats per block */
PyFloat_CompactFreeList(&bc, &bf, &fsum);
u = PyFloat_ClearFreeList();
if (!Py_VerboseFlag)
return;
fprintf(stderr, "# cleanup floats");
if (!fsum) {
if (!u) {
fprintf(stderr, "\n");
}
else {
fprintf(stderr,
": %" PY_FORMAT_SIZE_T "d unfreed float%s in %"
PY_FORMAT_SIZE_T "d out of %"
PY_FORMAT_SIZE_T "d block%s\n",
fsum, fsum == 1 ? "" : "s",
bc - bf, bc, bc == 1 ? "" : "s");
": %d unfreed float%s\n",
u, u == 1 ? "" : "s");
}
if (Py_VerboseFlag > 1) {
list = block_list;
......
......@@ -1296,35 +1296,33 @@ _PyInt_Init(void)
return 1;
}
void
PyInt_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum)
int
PyInt_ClearFreeList(void)
{
PyIntObject *p;
PyIntBlock *list, *next;
unsigned int ctr;
size_t bc = 0, bf = 0; /* block count, number of freed blocks */
size_t isum = 0; /* total unfreed ints */
int irem; /* remaining unfreed ints per block */
int i;
int u; /* remaining unfreed ints per block */
int freelist_size = 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++) {
u = 0;
for (i = 0, p = &list->objects[0];
i < N_INTOBJECTS;
i++, p++) {
if (PyInt_CheckExact(p) && p->ob_refcnt != 0)
irem++;
u++;
}
next = list->next;
if (irem) {
if (u) {
list->next = block_list;
block_list = list;
for (ctr = 0, p = &list->objects[0];
ctr < N_INTOBJECTS;
ctr++, p++) {
for (i = 0, p = &list->objects[0];
i < N_INTOBJECTS;
i++, p++) {
if (!PyInt_CheckExact(p) ||
p->ob_refcnt == 0) {
Py_TYPE(p) = (struct _typeobject *)
......@@ -1345,15 +1343,12 @@ PyInt_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum)
}
else {
PyMem_FREE(list);
bf++;
}
isum += irem;
freelist_size += u;
list = next;
}
*pbc = bc;
*pbf = bf;
*bsum = isum;
return freelist_size;
}
void
......@@ -1361,12 +1356,10 @@ PyInt_Fini(void)
{
PyIntObject *p;
PyIntBlock *list;
unsigned int ctr;
size_t bc, bf; /* block count, number of freed blocks */
size_t isum; /* total unfreed ints per block */
int i;
int u; /* total unfreed ints per block */
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
int i;
PyIntObject **q;
i = NSMALLNEGINTS + NSMALLPOSINTS;
......@@ -1376,27 +1369,24 @@ PyInt_Fini(void)
*q++ = NULL;
}
#endif
PyInt_CompactFreeList(&bc, &bf, &isum);
u = PyInt_ClearFreeList();
if (!Py_VerboseFlag)
return;
fprintf(stderr, "# cleanup ints");
if (!isum) {
if (!u) {
fprintf(stderr, "\n");
}
else {
fprintf(stderr,
": %" PY_FORMAT_SIZE_T "d unfreed int%s in %"
PY_FORMAT_SIZE_T "d out of %"
PY_FORMAT_SIZE_T "d block%s\n",
isum, isum == 1 ? "" : "s",
bc - bf, bc, bc == 1 ? "" : "s");
": %d unfreed int%s\n",
u, u == 1 ? "" : "s");
}
if (Py_VerboseFlag > 1) {
list = block_list;
while (list != NULL) {
for (ctr = 0, p = &list->objects[0];
ctr < N_INTOBJECTS;
ctr++, p++) {
for (i = 0, p = &list->objects[0];
i < N_INTOBJECTS;
i++, p++) {
if (PyInt_CheckExact(p) && p->ob_refcnt != 0)
/* XXX(twouters) cast refcount to
long until %zd is universally
......
......@@ -829,32 +829,12 @@ PyDoc_STRVAR(sys_clear_type_cache__doc__,
Clear the internal type lookup cache.");
static PyObject *
sys_compact_freelists(PyObject* self, PyObject* args)
{
size_t isum, ibc, ibf;
size_t fsum, fbc, fbf;
PyInt_CompactFreeList(&ibc, &ibf, &isum);
PyFloat_CompactFreeList(&fbc, &fbf, &fsum);
return Py_BuildValue("(kkk)(kkk)", isum, ibc, ibf,
fsum, fbc, fbf);
}
PyDoc_STRVAR(sys_compact_freelists__doc__,
"_compact_freelists() -> ((remaing_objects, total_blocks, freed_blocks), ...)\n\
Compact the free lists of ints and floats.");
static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
{"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
callstats_doc},
{"_clear_type_cache", sys_clear_type_cache, METH_NOARGS,
sys_clear_type_cache__doc__},
{"_compact_freelists", sys_compact_freelists, METH_NOARGS,
sys_compact_freelists__doc__},
{"_current_frames", sys_current_frames, METH_NOARGS,
current_frames_doc},
{"displayhook", sys_displayhook, METH_O, displayhook_doc},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment