[python3] add a sys._debugmallocstats() function (patch 147)
dmalcolm
dmalcolm at fedoraproject.org
Fri Sep 16 23:29:10 UTC 2011
commit ab415c6cddafcf5b295bf4433c2142a84c0f8e64
Author: David Malcolm <dmalcolm at redhat.com>
Date: Fri Sep 16 19:28:20 2011 -0400
add a sys._debugmallocstats() function (patch 147)
* Fri Sep 16 2011 David Malcolm <dmalcolm at redhat.com> - 3.2.2-6
- add a sys._debugmallocstats() function (patch 147)
00147-add-debug-malloc-stats.patch | 590 ++++++++++++++++++++++++++++++++++++
python3.spec | 11 +-
2 files changed, 600 insertions(+), 1 deletions(-)
---
diff --git a/00147-add-debug-malloc-stats.patch b/00147-add-debug-malloc-stats.patch
new file mode 100644
index 0000000..e2a8342
--- /dev/null
+++ b/00147-add-debug-malloc-stats.patch
@@ -0,0 +1,590 @@
+diff -up Python-3.2.2/Include/dictobject.h.add-debug-malloc-stats Python-3.2.2/Include/dictobject.h
+--- Python-3.2.2/Include/dictobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/dictobject.h 2011-09-16 18:57:24.969825060 -0400
+@@ -156,6 +156,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItemStr
+ PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
+ PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
+
++PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Include/floatobject.h.add-debug-malloc-stats Python-3.2.2/Include/floatobject.h
+--- Python-3.2.2/Include/floatobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/floatobject.h 2011-09-16 18:57:24.970825060 -0400
+@@ -110,6 +110,8 @@ PyAPI_FUNC(double) _PyFloat_Unpack8(cons
+ /* free list api */
+ PyAPI_FUNC(int) PyFloat_ClearFreeList(void);
+
++PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
++
+ /* Format the object based on the format_spec, as defined in PEP 3101
+ (Advanced String Formatting). */
+ PyAPI_FUNC(PyObject *) _PyFloat_FormatAdvanced(PyObject *obj,
+diff -up Python-3.2.2/Include/frameobject.h.add-debug-malloc-stats Python-3.2.2/Include/frameobject.h
+--- Python-3.2.2/Include/frameobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/frameobject.h 2011-09-16 18:57:24.970825060 -0400
+@@ -79,6 +79,8 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(Py
+
+ PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
+
++PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);
++
+ /* Return the line of code the frame is currently executing. */
+ PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
+
+diff -up Python-3.2.2/Include/listobject.h.add-debug-malloc-stats Python-3.2.2/Include/listobject.h
+--- Python-3.2.2/Include/listobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/listobject.h 2011-09-16 18:57:24.971825060 -0400
+@@ -71,6 +71,8 @@ PyAPI_FUNC(PyObject *) _PyList_Extend(Py
+ #define PyList_GET_SIZE(op) Py_SIZE(op)
+ #endif
+
++PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Include/methodobject.h.add-debug-malloc-stats Python-3.2.2/Include/methodobject.h
+--- Python-3.2.2/Include/methodobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/methodobject.h 2011-09-16 18:57:24.971825060 -0400
+@@ -81,6 +81,10 @@ typedef struct {
+
+ PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
+
++PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
++PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
++
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Include/object.h.add-debug-malloc-stats Python-3.2.2/Include/object.h
+--- Python-3.2.2/Include/object.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/object.h 2011-09-16 18:57:24.972825060 -0400
+@@ -919,6 +919,13 @@ PyAPI_DATA(PyObject *) _PyTrash_delete_l
+ else \
+ _PyTrash_deposit_object((PyObject*)op);
+
++PyAPI_FUNC(void)
++_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
++ size_t sizeof_block);
++
++PyAPI_FUNC(void)
++_PyObject_DebugTypeStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Include/objimpl.h.add-debug-malloc-stats Python-3.2.2/Include/objimpl.h
+--- Python-3.2.2/Include/objimpl.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/objimpl.h 2011-09-16 18:57:24.972825060 -0400
+@@ -101,13 +101,13 @@ PyAPI_FUNC(void) PyObject_Free(void *);
+
+ /* Macros */
+ #ifdef WITH_PYMALLOC
++PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out);
+ #ifdef PYMALLOC_DEBUG /* WITH_PYMALLOC && PYMALLOC_DEBUG */
+ PyAPI_FUNC(void *) _PyObject_DebugMalloc(size_t nbytes);
+ PyAPI_FUNC(void *) _PyObject_DebugRealloc(void *p, size_t nbytes);
+ PyAPI_FUNC(void) _PyObject_DebugFree(void *p);
+ PyAPI_FUNC(void) _PyObject_DebugDumpAddress(const void *p);
+ PyAPI_FUNC(void) _PyObject_DebugCheckAddress(const void *p);
+-PyAPI_FUNC(void) _PyObject_DebugMallocStats(void);
+ PyAPI_FUNC(void *) _PyObject_DebugMallocApi(char api, size_t nbytes);
+ PyAPI_FUNC(void *) _PyObject_DebugReallocApi(char api, void *p, size_t nbytes);
+ PyAPI_FUNC(void) _PyObject_DebugFreeApi(char api, void *p);
+diff -up Python-3.2.2/Include/setobject.h.add-debug-malloc-stats Python-3.2.2/Include/setobject.h
+--- Python-3.2.2/Include/setobject.h.add-debug-malloc-stats 2011-09-16 19:10:58.448817301 -0400
++++ Python-3.2.2/Include/setobject.h 2011-09-16 19:12:16.343816559 -0400
+@@ -101,6 +101,8 @@ PyAPI_FUNC(PyObject *) PySet_Pop(PyObjec
+ PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
+ #endif
+
++PyAPI_FUNC(void) _PySet_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Include/tupleobject.h.add-debug-malloc-stats Python-3.2.2/Include/tupleobject.h
+--- Python-3.2.2/Include/tupleobject.h.add-debug-malloc-stats 2011-09-16 19:10:45.540817425 -0400
++++ Python-3.2.2/Include/tupleobject.h 2011-09-16 19:12:41.446816320 -0400
+@@ -63,6 +63,7 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(P
+ #endif
+
+ PyAPI_FUNC(int) PyTuple_ClearFreeList(void);
++PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);
+
+ #ifdef __cplusplus
+ }
+diff -up Python-3.2.2/Include/unicodeobject.h.add-debug-malloc-stats Python-3.2.2/Include/unicodeobject.h
+--- Python-3.2.2/Include/unicodeobject.h.add-debug-malloc-stats 2011-09-03 12:16:40.000000000 -0400
++++ Python-3.2.2/Include/unicodeobject.h 2011-09-16 18:57:24.973825060 -0400
+@@ -1670,6 +1670,8 @@ PyAPI_FUNC(Py_UNICODE*) PyUnicode_AsUnic
+ );
+ #endif /* Py_LIMITED_API */
+
++PyAPI_FUNC(void) _PyUnicode_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-3.2.2/Lib/test/test_sys.py.add-debug-malloc-stats Python-3.2.2/Lib/test/test_sys.py
+--- Python-3.2.2/Lib/test/test_sys.py.add-debug-malloc-stats 2011-09-16 18:57:24.940825060 -0400
++++ Python-3.2.2/Lib/test/test_sys.py 2011-09-16 19:23:50.415809940 -0400
+@@ -564,6 +564,18 @@ class SysModuleTest(unittest.TestCase):
+ expected = None
+ self.check_fsencoding(fs_encoding, expected)
+
++ def test_debugmallocstats(self):
++ # Test sys._debugmallocstats()
++
++ import subprocess
++
++ # Verify writing to stderr:
++ p = subprocess.Popen([sys.executable,
++ '-c', 'import sys; sys._debugmallocstats()'],
++ stderr=subprocess.PIPE)
++ out, err = p.communicate()
++ p.wait()
++ self.assertIn(b"arenas allocated current", err)
+
+ class SizeofTest(unittest.TestCase):
+
+diff -up Python-3.2.2/Objects/classobject.c.add-debug-malloc-stats Python-3.2.2/Objects/classobject.c
+--- Python-3.2.2/Objects/classobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/classobject.c 2011-09-16 18:57:24.975825060 -0400
+@@ -399,6 +399,15 @@ PyMethod_Fini(void)
+ (void)PyMethod_ClearFreeList();
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyMethod_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyMethodObject",
++ numfree, sizeof(PyMethodObject));
++}
++
+ /* ------------------------------------------------------------------------
+ * instance method
+ */
+diff -up Python-3.2.2/Objects/dictobject.c.add-debug-malloc-stats Python-3.2.2/Objects/dictobject.c
+--- Python-3.2.2/Objects/dictobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/dictobject.c 2011-09-16 18:57:24.976825060 -0400
+@@ -217,6 +217,15 @@ show_track(void)
+ static PyDictObject *free_list[PyDict_MAXFREELIST];
+ static int numfree = 0;
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyDict_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyDictObject", numfree, sizeof(PyDictObject));
++}
++
++
+ void
+ PyDict_Fini(void)
+ {
+diff -up Python-3.2.2/Objects/floatobject.c.add-debug-malloc-stats Python-3.2.2/Objects/floatobject.c
+--- Python-3.2.2/Objects/floatobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/floatobject.c 2011-09-16 18:57:24.981825060 -0400
+@@ -50,6 +50,22 @@ typedef struct _floatblock PyFloatBlock;
+ static PyFloatBlock *block_list = NULL;
+ static PyFloatObject *free_list = NULL;
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyFloat_DebugMallocStats(FILE *out)
++{
++ int num_blocks = 0;
++ PyFloatBlock *block;
++
++ /* Walk the block list, counting */
++ for (block = block_list; block ; block = block->next) {
++ num_blocks++;
++ }
++
++ _PyDebugAllocatorStats(out,
++ "PyFloatBlock", num_blocks, sizeof(PyFloatBlock));
++}
++
+ static PyFloatObject *
+ fill_free_list(void)
+ {
+diff -up Python-3.2.2/Objects/frameobject.c.add-debug-malloc-stats Python-3.2.2/Objects/frameobject.c
+--- Python-3.2.2/Objects/frameobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/frameobject.c 2011-09-16 18:57:24.982825060 -0400
+@@ -953,3 +953,13 @@ PyFrame_Fini(void)
+ Py_XDECREF(builtin_object);
+ builtin_object = NULL;
+ }
++
++/* Print summary info about the state of the optimized allocator */
++void
++_PyFrame_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyFrameObject",
++ numfree, sizeof(PyFrameObject));
++}
++
+diff -up Python-3.2.2/Objects/listobject.c.add-debug-malloc-stats Python-3.2.2/Objects/listobject.c
+--- Python-3.2.2/Objects/listobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/listobject.c 2011-09-16 18:57:24.983825060 -0400
+@@ -109,6 +109,15 @@ PyList_Fini(void)
+ }
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyList_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyListObject",
++ numfree, sizeof(PyListObject));
++}
++
+ PyObject *
+ PyList_New(Py_ssize_t size)
+ {
+diff -up Python-3.2.2/Objects/methodobject.c.add-debug-malloc-stats Python-3.2.2/Objects/methodobject.c
+--- Python-3.2.2/Objects/methodobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/methodobject.c 2011-09-16 18:57:24.983825060 -0400
+@@ -303,6 +303,15 @@ PyCFunction_Fini(void)
+ (void)PyCFunction_ClearFreeList();
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyCFunction_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyCFunction",
++ numfree, sizeof(PyCFunction));
++}
++
+ /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
+ but it's part of the API so we need to keep a function around that
+ existing C extensions can call.
+diff -up Python-3.2.2/Objects/object.c.add-debug-malloc-stats Python-3.2.2/Objects/object.c
+--- Python-3.2.2/Objects/object.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/object.c 2011-09-16 19:04:20.351821098 -0400
+@@ -1781,6 +1781,19 @@ PyMem_Free(void *p)
+ PyMem_FREE(p);
+ }
+
++void
++_PyObject_DebugTypeStats(FILE *out)
++{
++ _PyCFunction_DebugMallocStats(out);
++ _PyDict_DebugMallocStats(out);
++ _PyFloat_DebugMallocStats(out);
++ _PyFrame_DebugMallocStats(out);
++ _PyList_DebugMallocStats(out);
++ _PyMethod_DebugMallocStats(out);
++ _PySet_DebugMallocStats(out);
++ _PyTuple_DebugMallocStats(out);
++ _PyUnicode_DebugMallocStats(out);
++}
+
+ /* These methods are used to control infinite recursion in repr, str, print,
+ etc. Container objects that may recursively contain themselves,
+diff -up Python-3.2.2/Objects/obmalloc.c.add-debug-malloc-stats Python-3.2.2/Objects/obmalloc.c
+--- Python-3.2.2/Objects/obmalloc.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/obmalloc.c 2011-09-16 18:57:24.985825060 -0400
+@@ -508,12 +508,10 @@ static struct arena_object* usable_arena
+ /* Number of arenas allocated that haven't been free()'d. */
+ static size_t narenas_currently_allocated = 0;
+
+-#ifdef PYMALLOC_DEBUG
+ /* Total number of times malloc() called to allocate an arena. */
+ static size_t ntimes_arena_allocated = 0;
+ /* High water mark (max value ever seen) for narenas_currently_allocated. */
+ static size_t narenas_highwater = 0;
+-#endif
+
+ /* Allocate a new arena. If we run out of memory, return NULL. Else
+ * allocate a new arena, and return the address of an arena_object
+@@ -528,7 +526,7 @@ new_arena(void)
+
+ #ifdef PYMALLOC_DEBUG
+ if (Py_GETENV("PYTHONMALLOCSTATS"))
+- _PyObject_DebugMallocStats();
++ _PyObject_DebugMallocStats(stderr);
+ #endif
+ if (unused_arena_objects == NULL) {
+ uint i;
+@@ -588,11 +586,9 @@ new_arena(void)
+ }
+
+ ++narenas_currently_allocated;
+-#ifdef PYMALLOC_DEBUG
+ ++ntimes_arena_allocated;
+ if (narenas_currently_allocated > narenas_highwater)
+ narenas_highwater = narenas_currently_allocated;
+-#endif
+ arenaobj->freepools = NULL;
+ /* pool_address <- first pool-aligned address in the arena
+ nfreepools <- number of whole pools that fit after alignment */
+@@ -1694,17 +1690,19 @@ _PyObject_DebugDumpAddress(const void *p
+ }
+ }
+
++#endif /* PYMALLOC_DEBUG */
++
+ static size_t
+-printone(const char* msg, size_t value)
++printone(FILE *out, const char* msg, size_t value)
+ {
+ int i, k;
+ char buf[100];
+ size_t origvalue = value;
+
+- fputs(msg, stderr);
++ fputs(msg, out);
+ for (i = (int)strlen(msg); i < 35; ++i)
+- fputc(' ', stderr);
+- fputc('=', stderr);
++ fputc(' ', out);
++ fputc('=', out);
+
+ /* Write the value with commas. */
+ i = 22;
+@@ -1725,17 +1723,32 @@ printone(const char* msg, size_t value)
+
+ while (i >= 0)
+ buf[i--] = ' ';
+- fputs(buf, stderr);
++ fputs(buf, out);
+
+ return origvalue;
+ }
+
+-/* Print summary info to stderr about the state of pymalloc's structures.
++void
++_PyDebugAllocatorStats(FILE *out,
++ const char *block_name, int num_blocks, size_t sizeof_block)
++{
++ char buf1[128];
++ char buf2[128];
++ PyOS_snprintf(buf1, sizeof(buf1),
++ "%d %ss * %zd bytes each",
++ num_blocks, block_name, sizeof_block);
++ PyOS_snprintf(buf2, sizeof(buf2),
++ "%48s ", buf1);
++ (void)printone(out, buf2, num_blocks * sizeof_block);
++}
++
++
++/* Print summary info to "out" about the state of pymalloc's structures.
+ * In Py_DEBUG mode, also perform some expensive internal consistency
+ * checks.
+ */
+ void
+-_PyObject_DebugMallocStats(void)
++_PyObject_DebugMallocStats(FILE *out)
+ {
+ uint i;
+ const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
+@@ -1764,7 +1777,7 @@ _PyObject_DebugMallocStats(void)
+ size_t total;
+ char buf[128];
+
+- fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
++ fprintf(out, "Small block threshold = %d, in %u size classes.\n",
+ SMALL_REQUEST_THRESHOLD, numclasses);
+
+ for (i = 0; i < numclasses; ++i)
+@@ -1820,10 +1833,10 @@ _PyObject_DebugMallocStats(void)
+ }
+ assert(narenas == narenas_currently_allocated);
+
+- fputc('\n', stderr);
++ fputc('\n', out);
+ fputs("class size num pools blocks in use avail blocks\n"
+ "----- ---- --------- ------------- ------------\n",
+- stderr);
++ out);
+
+ for (i = 0; i < numclasses; ++i) {
+ size_t p = numpools[i];
+@@ -1834,7 +1847,7 @@ _PyObject_DebugMallocStats(void)
+ assert(b == 0 && f == 0);
+ continue;
+ }
+- fprintf(stderr, "%5u %6u "
++ fprintf(out, "%5u %6u "
+ "%11" PY_FORMAT_SIZE_T "u "
+ "%15" PY_FORMAT_SIZE_T "u "
+ "%13" PY_FORMAT_SIZE_T "u\n",
+@@ -1844,36 +1857,35 @@ _PyObject_DebugMallocStats(void)
+ pool_header_bytes += p * POOL_OVERHEAD;
+ quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
+ }
+- fputc('\n', stderr);
+- (void)printone("# times object malloc called", serialno);
+-
+- (void)printone("# arenas allocated total", ntimes_arena_allocated);
+- (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
+- (void)printone("# arenas highwater mark", narenas_highwater);
+- (void)printone("# arenas allocated current", narenas);
++ fputc('\n', out);
++#ifdef PYMALLOC_DEBUG
++ (void)printone(out, "# times object malloc called", serialno);
++#endif
++ (void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
++ (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
++ (void)printone(out, "# arenas highwater mark", narenas_highwater);
++ (void)printone(out, "# arenas allocated current", narenas);
+
+ PyOS_snprintf(buf, sizeof(buf),
+ "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
+ narenas, ARENA_SIZE);
+- (void)printone(buf, narenas * ARENA_SIZE);
++ (void)printone(out, buf, narenas * ARENA_SIZE);
+
+- fputc('\n', stderr);
++ fputc('\n', out);
+
+- total = printone("# bytes in allocated blocks", allocated_bytes);
+- total += printone("# bytes in available blocks", available_bytes);
++ total = printone(out, "# bytes in allocated blocks", allocated_bytes);
++ total += printone(out, "# bytes in available blocks", available_bytes);
+
+ PyOS_snprintf(buf, sizeof(buf),
+ "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
+- total += printone(buf, (size_t)numfreepools * POOL_SIZE);
++ total += printone(out, buf, (size_t)numfreepools * POOL_SIZE);
+
+- total += printone("# bytes lost to pool headers", pool_header_bytes);
+- total += printone("# bytes lost to quantization", quantization);
+- total += printone("# bytes lost to arena alignment", arena_alignment);
+- (void)printone("Total", total);
++ total += printone(out, "# bytes lost to pool headers", pool_header_bytes);
++ total += printone(out, "# bytes lost to quantization", quantization);
++ total += printone(out, "# bytes lost to arena alignment", arena_alignment);
++ (void)printone(out, "Total", total);
+ }
+
+-#endif /* PYMALLOC_DEBUG */
+-
+ #ifdef Py_USING_MEMORY_DEBUGGER
+ /* Make this function last so gcc won't inline it since the definition is
+ * after the reference.
+diff -up Python-3.2.2/Objects/setobject.c.add-debug-malloc-stats Python-3.2.2/Objects/setobject.c
+--- Python-3.2.2/Objects/setobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/setobject.c 2011-09-16 18:57:24.986825060 -0400
+@@ -1090,6 +1090,16 @@ PySet_Fini(void)
+ Py_CLEAR(emptyfrozenset);
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PySet_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PySetObject",
++ numfree, sizeof(PySetObject));
++}
++
++
+ static PyObject *
+ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+diff -up Python-3.2.2/Objects/tupleobject.c.add-debug-malloc-stats Python-3.2.2/Objects/tupleobject.c
+--- Python-3.2.2/Objects/tupleobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/tupleobject.c 2011-09-16 18:57:24.987825060 -0400
+@@ -44,6 +44,22 @@ show_track(void)
+ }
+ #endif
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyTuple_DebugMallocStats(FILE *out)
++{
++#if PyTuple_MAXSAVESIZE > 0
++ int i;
++ char buf[128];
++ for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
++ PyOS_snprintf(buf, sizeof(buf),
++ "free %d-sized PyTupleObject", i);
++ _PyDebugAllocatorStats(out,
++ buf,
++ numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i));
++ }
++#endif
++}
+
+ PyObject *
+ PyTuple_New(register Py_ssize_t size)
+diff -up Python-3.2.2/Objects/unicodeobject.c.add-debug-malloc-stats Python-3.2.2/Objects/unicodeobject.c
+--- Python-3.2.2/Objects/unicodeobject.c.add-debug-malloc-stats 2011-09-03 12:16:47.000000000 -0400
++++ Python-3.2.2/Objects/unicodeobject.c 2011-09-16 18:57:24.990825060 -0400
+@@ -10063,6 +10063,12 @@ _PyUnicode_Fini(void)
+ (void)PyUnicode_ClearFreeList();
+ }
+
++void _PyUnicode_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out, "free PyUnicodeObject", numfree,
++ sizeof(PyUnicodeObject));
++}
++
+ void
+ PyUnicode_InternInPlace(PyObject **p)
+ {
+diff -up Python-3.2.2/Python/pythonrun.c.add-debug-malloc-stats Python-3.2.2/Python/pythonrun.c
+--- Python-3.2.2/Python/pythonrun.c.add-debug-malloc-stats 2011-09-16 19:24:44.747809422 -0400
++++ Python-3.2.2/Python/pythonrun.c 2011-09-16 19:25:00.024809277 -0400
+@@ -547,7 +547,7 @@ Py_Finalize(void)
+ #endif /* Py_TRACE_REFS */
+ #ifdef PYMALLOC_DEBUG
+ if (Py_GETENV("PYTHONMALLOCSTATS"))
+- _PyObject_DebugMallocStats();
++ _PyObject_DebugMallocStats(stderr);
+ #endif
+
+ call_ll_exitfuncs();
+diff -up Python-3.2.2/Python/sysmodule.c.add-debug-malloc-stats Python-3.2.2/Python/sysmodule.c
+--- Python-3.2.2/Python/sysmodule.c.add-debug-malloc-stats 2011-09-03 12:16:49.000000000 -0400
++++ Python-3.2.2/Python/sysmodule.c 2011-09-16 19:18:45.806812845 -0400
+@@ -994,6 +994,25 @@ a 11-tuple where the entries in the tupl
+ extern "C" {
+ #endif
+
++static PyObject *
++sys_debugmallocstats(PyObject *self, PyObject *args)
++{
++ _PyObject_DebugMallocStats(stderr);
++ fputc('\n', stderr);
++ _PyObject_DebugTypeStats(stderr);
++
++ Py_RETURN_NONE;
++}
++PyDoc_STRVAR(debugmallocstats_doc,
++"_debugmallocstats([file])\n\
++\n\
++Print summary info to stderr about the state of\n\
++pymalloc's structures.\n\
++\n\
++In Py_DEBUG mode, also perform some expensive internal consistency\n\
++checks.\n\
++");
++
+ #ifdef Py_TRACE_REFS
+ /* Defined in objects.c because it uses static globals if that file */
+ extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
+@@ -1090,6 +1109,8 @@ static PyMethodDef sys_methods[] = {
+ {"settrace", sys_settrace, METH_O, settrace_doc},
+ {"gettrace", sys_gettrace, METH_NOARGS, gettrace_doc},
+ {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
++ {"_debugmallocstats", sys_debugmallocstats, METH_VARARGS,
++ debugmallocstats_doc},
+ {NULL, NULL} /* sentinel */
+ };
+
diff --git a/python3.spec b/python3.spec
index f102431..cb64c64 100644
--- a/python3.spec
+++ b/python3.spec
@@ -122,7 +122,7 @@
Summary: Version 3 of the Python programming language aka Python 3000
Name: python3
Version: %{pybasever}.2
-Release: 5%{?dist}
+Release: 6%{?dist}
License: Python
Group: Development/Languages
@@ -353,6 +353,11 @@ Patch143: 00143-tsc-on-ppc.patch
# (rhbz#563986)
Patch146: 00146-hashlib-fips.patch
+# Add a sys._debugmallocstats() function
+# Based on patch 202 from RHEL 5's python.spec, with updates from rhbz#737198
+# Not yet sent upstream
+Patch147: 00147-add-debug-malloc-stats.patch
+
# (New patches go here ^^^)
#
# When adding new patches to "python" and "python3" in Fedora 17 onwards,
@@ -562,6 +567,7 @@ done
# 00144: not for python3
# 00145: not for python3
%patch146 -p1
+%patch147 -p1
# Currently (2010-01-15), http://docs.python.org/library is for 2.6, and there
# are many differences between 2.6 and the Python 3 library.
@@ -1373,6 +1379,9 @@ rm -fr %{buildroot}
# ======================================================
%changelog
+* Fri Sep 16 2011 David Malcolm <dmalcolm at redhat.com> - 3.2.2-6
+- add a sys._debugmallocstats() function (patch 147)
+
* Wed Sep 14 2011 David Malcolm <dmalcolm at redhat.com> - 3.2.2-5
- support OpenSSL FIPS mode in _hashlib and hashlib; don't build the _md5 and
_sha* modules, relying on _hashlib in hashlib (rhbz#563986; patch 146)
More information about the scm-commits
mailing list