mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
Implemented Martin's suggestion to clear the free lists during the garbage collection of the highest generation.
This commit is contained in:
parent
50361d4d9b
commit
3b718a79af
15 changed files with 131 additions and 25 deletions
|
@ -63,3 +63,10 @@ There are some useful functions that are useful for working with method objects.
|
|||
.. cfunction:: PyObject* PyMethod_GET_SELF(PyObject *meth)
|
||||
|
||||
Macro version of :cfunc:`PyMethod_Self` which avoids error checking.
|
||||
|
||||
|
||||
.. cfunction:: int PyMethod_ClearFreeList(void)
|
||||
|
||||
Clear the free list. Return the total number of freed items.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
|
|
@ -115,3 +115,10 @@ Tuple Objects
|
|||
|
||||
.. versionchanged:: 2.2
|
||||
Removed unused third parameter, *last_is_sticky*.
|
||||
|
||||
|
||||
.. cfunction:: int PyMethod_ClearFreeList(void)
|
||||
|
||||
Clear the free list. Return the total number of freed items.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
|
|
@ -89,6 +89,13 @@ access internal read-only data of Unicode objects:
|
|||
Return a pointer to the internal buffer of the object. *o* has to be a
|
||||
:ctype:`PyUnicodeObject` (not checked).
|
||||
|
||||
|
||||
.. cfunction:: int PyUnicode_ClearFreeList(void)
|
||||
|
||||
Clear the free list. Return the total number of freed items.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
Unicode provides many different character properties. The most often needed ones
|
||||
are available through these macros which are mapped to C functions depending on
|
||||
the Python configuration.
|
||||
|
|
|
@ -74,6 +74,7 @@ PyAPI_FUNC(PyObject *) _PyInstance_Lookup(PyObject *pinst, PyObject *name);
|
|||
|
||||
PyAPI_FUNC(int) PyClass_IsSubclass(PyObject *, PyObject *);
|
||||
|
||||
PyAPI_FUNC(int) PyMethod_ClearFreeList(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ PyAPI_FUNC(PyObject **) PyFrame_ExtendStack(PyFrameObject *, int, int);
|
|||
PyAPI_FUNC(void) PyFrame_LocalsToFast(PyFrameObject *, int);
|
||||
PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
|
||||
|
||||
PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -85,6 +85,8 @@ typedef struct {
|
|||
PyObject *m_module; /* The __module__ attribute, can be anything */
|
||||
} PyCFunctionObject;
|
||||
|
||||
PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,8 @@ PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...);
|
|||
/* Macro, *only* to be used to fill in brand new tuples */
|
||||
#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = v)
|
||||
|
||||
PyAPI_FUNC(int) PyTuple_ClearFreeList(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -209,6 +209,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
|
|||
# define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS2_AsDefaultEncodedString
|
||||
# define _PyUnicode_Fini _PyUnicodeUCS2_Fini
|
||||
# define _PyUnicode_Init _PyUnicodeUCS2_Init
|
||||
# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist
|
||||
# define _PyUnicode_IsAlpha _PyUnicodeUCS2_IsAlpha
|
||||
# define _PyUnicode_IsDecimalDigit _PyUnicodeUCS2_IsDecimalDigit
|
||||
# define _PyUnicode_IsDigit _PyUnicodeUCS2_IsDigit
|
||||
|
@ -295,6 +296,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE;
|
|||
# define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS4_AsDefaultEncodedString
|
||||
# define _PyUnicode_Fini _PyUnicodeUCS4_Fini
|
||||
# define _PyUnicode_Init _PyUnicodeUCS4_Init
|
||||
# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist
|
||||
# define _PyUnicode_IsAlpha _PyUnicodeUCS4_IsAlpha
|
||||
# define _PyUnicode_IsDecimalDigit _PyUnicodeUCS4_IsDecimalDigit
|
||||
# define _PyUnicode_IsDigit _PyUnicodeUCS4_IsDigit
|
||||
|
@ -403,6 +405,8 @@ extern const unsigned char _Py_ascii_whitespace[];
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(int) PyUnicode_ClearFreeList(void);
|
||||
|
||||
/* --- Unicode Type ------------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 1?
|
|||
Core and builtins
|
||||
-----------------
|
||||
|
||||
- Clear all free list during a gc.collect() of the highest generation in order
|
||||
to allow pymalloc to free more arenas. Python may give back memory to the
|
||||
OS earlier.
|
||||
|
||||
- Issue #2045: Fix an infinite recursion triggered when printing a subclass of
|
||||
collections.defaultdict, if its default_factory is set to a bound method.
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#include "frameobject.h" /* for PyFrame_ClearFreeList */
|
||||
|
||||
/* Get an object's GC head */
|
||||
#define AS_GC(o) ((PyGC_Head *)(o)-1)
|
||||
|
@ -722,6 +723,21 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
|
|||
}
|
||||
}
|
||||
|
||||
/* Clear all free lists
|
||||
* All free lists are cleared during the collection of the highest generation.
|
||||
* Allocated items in the free list may keep a pymalloc arena occupied.
|
||||
* Clearing the free lists may give back memory to the OS earlier.
|
||||
*/
|
||||
static void
|
||||
clear_freelists(void)
|
||||
{
|
||||
(void)PyMethod_ClearFreeList();
|
||||
(void)PyFrame_ClearFreeList();
|
||||
(void)PyCFunction_ClearFreeList();
|
||||
(void)PyTuple_ClearFreeList();
|
||||
(void)PyUnicode_ClearFreeList();
|
||||
}
|
||||
|
||||
/* This is the main function. Read this to understand how the
|
||||
* collection process works. */
|
||||
static Py_ssize_t
|
||||
|
@ -874,6 +890,12 @@ collect(int generation)
|
|||
*/
|
||||
(void)handle_finalizers(&finalizers, old);
|
||||
|
||||
/* Clear free list only during the collection of the higest
|
||||
* generation */
|
||||
if (generation == NUM_GENERATIONS-1) {
|
||||
clear_freelists();
|
||||
}
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
if (gc_str == NULL)
|
||||
gc_str = PyString_FromString("garbage collection");
|
||||
|
|
|
@ -2626,9 +2626,11 @@ PyTypeObject PyMethod_Type = {
|
|||
|
||||
/* Clear out the free list */
|
||||
|
||||
void
|
||||
PyMethod_Fini(void)
|
||||
int
|
||||
PyMethod_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = numfree;
|
||||
|
||||
while (free_list) {
|
||||
PyMethodObject *im = free_list;
|
||||
free_list = (PyMethodObject *)(im->im_self);
|
||||
|
@ -2636,4 +2638,11 @@ PyMethod_Fini(void)
|
|||
numfree--;
|
||||
}
|
||||
assert(numfree == 0);
|
||||
return freelist_size;
|
||||
}
|
||||
|
||||
void
|
||||
PyMethod_Fini(void)
|
||||
{
|
||||
(void)PyMethod_ClearFreeList();
|
||||
}
|
||||
|
|
|
@ -889,10 +889,11 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
|
|||
}
|
||||
|
||||
/* Clear out the free list */
|
||||
|
||||
void
|
||||
PyFrame_Fini(void)
|
||||
int
|
||||
PyFrame_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = numfree;
|
||||
|
||||
while (free_list != NULL) {
|
||||
PyFrameObject *f = free_list;
|
||||
free_list = free_list->f_back;
|
||||
|
@ -900,6 +901,13 @@ PyFrame_Fini(void)
|
|||
--numfree;
|
||||
}
|
||||
assert(numfree == 0);
|
||||
return freelist_size;
|
||||
}
|
||||
|
||||
void
|
||||
PyFrame_Fini(void)
|
||||
{
|
||||
(void)PyFrame_ClearFreeList();
|
||||
Py_XDECREF(builtin_object);
|
||||
builtin_object = NULL;
|
||||
}
|
||||
|
|
|
@ -353,9 +353,11 @@ Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
|
|||
|
||||
/* Clear out the free list */
|
||||
|
||||
void
|
||||
PyCFunction_Fini(void)
|
||||
int
|
||||
PyCFunction_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = numfree;
|
||||
|
||||
while (free_list) {
|
||||
PyCFunctionObject *v = free_list;
|
||||
free_list = (PyCFunctionObject *)(v->m_self);
|
||||
|
@ -363,6 +365,13 @@ PyCFunction_Fini(void)
|
|||
numfree--;
|
||||
}
|
||||
assert(numfree == 0);
|
||||
return freelist_size;
|
||||
}
|
||||
|
||||
void
|
||||
PyCFunction_Fini(void)
|
||||
{
|
||||
(void)PyCFunction_ClearFreeList();
|
||||
}
|
||||
|
||||
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
|
||||
|
|
|
@ -832,25 +832,38 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PyTuple_Fini(void)
|
||||
int
|
||||
PyTuple_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = 0;
|
||||
#if PyTuple_MAXSAVESIZE > 0
|
||||
int i;
|
||||
|
||||
Py_XDECREF(free_list[0]);
|
||||
free_list[0] = NULL;
|
||||
|
||||
for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
|
||||
PyTupleObject *p, *q;
|
||||
p = free_list[i];
|
||||
freelist_size += numfree[i];
|
||||
free_list[i] = NULL;
|
||||
numfree[i] = 0;
|
||||
while (p) {
|
||||
q = p;
|
||||
p = (PyTupleObject *)(p->ob_item[0]);
|
||||
PyObject_GC_Del(q);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return freelist_size;
|
||||
}
|
||||
|
||||
void
|
||||
PyTuple_Fini(void)
|
||||
{
|
||||
#if PyTuple_MAXSAVESIZE > 0
|
||||
/* empty tuples are used all over the place and applications may
|
||||
* rely on the fact that an empty tuple is a singleton. */
|
||||
Py_XDECREF(free_list[0]);
|
||||
free_list[0] = NULL;
|
||||
|
||||
(void)PyTuple_ClearFreeList();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -8853,10 +8853,29 @@ void _PyUnicode_Init(void)
|
|||
|
||||
/* Finalize the Unicode implementation */
|
||||
|
||||
int
|
||||
PyUnicode_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = numfree;
|
||||
PyUnicodeObject *u;
|
||||
|
||||
for (u = free_list; u != NULL;) {
|
||||
PyUnicodeObject *v = u;
|
||||
u = *(PyUnicodeObject **)u;
|
||||
if (v->str)
|
||||
PyMem_DEL(v->str);
|
||||
Py_XDECREF(v->defenc);
|
||||
PyObject_Del(v);
|
||||
numfree--;
|
||||
}
|
||||
free_list = NULL;
|
||||
assert(numfree == 0);
|
||||
return freelist_size;
|
||||
}
|
||||
|
||||
void
|
||||
_PyUnicode_Fini(void)
|
||||
{
|
||||
PyUnicodeObject *u;
|
||||
int i;
|
||||
|
||||
Py_XDECREF(unicode_empty);
|
||||
|
@ -8868,17 +8887,7 @@ _PyUnicode_Fini(void)
|
|||
unicode_latin1[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (u = free_list; u != NULL;) {
|
||||
PyUnicodeObject *v = u;
|
||||
u = *(PyUnicodeObject **)u;
|
||||
if (v->str)
|
||||
PyMem_DEL(v->str);
|
||||
Py_XDECREF(v->defenc);
|
||||
PyObject_Del(v);
|
||||
}
|
||||
free_list = NULL;
|
||||
numfree = 0;
|
||||
(void)PyUnicode_ClearFreeList();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue