]> git.ipfire.org Git - people/stevee/ipfire-3.x.git/blob - python/patches/00147-add-debug-malloc-stats.patch
python: Update to 2.7.15
[people/stevee/ipfire-3.x.git] / python / patches / 00147-add-debug-malloc-stats.patch
1 diff -up Python-2.7.2/Include/dictobject.h.add-debug-malloc-stats Python-2.7.2/Include/dictobject.h
2 --- Python-2.7.2/Include/dictobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
3 +++ Python-2.7.2/Include/dictobject.h 2011-09-16 19:03:25.105821625 -0400
4 @@ -150,6 +150,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItemStr
5 PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
6 PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
7
8 +PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out);
9 +
10 #ifdef __cplusplus
11 }
12 #endif
13 diff -up Python-2.7.2/Include/floatobject.h.add-debug-malloc-stats Python-2.7.2/Include/floatobject.h
14 --- Python-2.7.2/Include/floatobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
15 +++ Python-2.7.2/Include/floatobject.h 2011-09-16 19:03:25.106821625 -0400
16 @@ -132,6 +132,7 @@ PyAPI_FUNC(PyObject *) _PyFloat_FormatAd
17 failure. Used in builtin_round in bltinmodule.c. */
18 PyAPI_FUNC(PyObject *) _Py_double_round(double x, int ndigits);
19
20 +PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
21
22
23 #ifdef __cplusplus
24 diff -up Python-2.7.2/Include/frameobject.h.add-debug-malloc-stats Python-2.7.2/Include/frameobject.h
25 --- Python-2.7.2/Include/frameobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
26 +++ Python-2.7.2/Include/frameobject.h 2011-09-16 19:03:25.107821625 -0400
27 @@ -80,6 +80,8 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(Py
28
29 PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
30
31 +PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);
32 +
33 /* Return the line of code the frame is currently executing. */
34 PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
35
36 diff -up Python-2.7.2/Include/intobject.h.add-debug-malloc-stats Python-2.7.2/Include/intobject.h
37 --- Python-2.7.2/Include/intobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
38 +++ Python-2.7.2/Include/intobject.h 2011-09-16 19:03:25.107821625 -0400
39 @@ -74,6 +74,8 @@ PyAPI_FUNC(PyObject *) _PyInt_FormatAdva
40 char *format_spec,
41 Py_ssize_t format_spec_len);
42
43 +PyAPI_FUNC(void) _PyInt_DebugMallocStats(FILE *out);
44 +
45 #ifdef __cplusplus
46 }
47 #endif
48 diff -up Python-2.7.2/Include/listobject.h.add-debug-malloc-stats Python-2.7.2/Include/listobject.h
49 --- Python-2.7.2/Include/listobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
50 +++ Python-2.7.2/Include/listobject.h 2011-09-16 19:03:25.107821625 -0400
51 @@ -62,6 +62,8 @@ PyAPI_FUNC(PyObject *) _PyList_Extend(Py
52 #define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v))
53 #define PyList_GET_SIZE(op) Py_SIZE(op)
54
55 +PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out);
56 +
57 #ifdef __cplusplus
58 }
59 #endif
60 diff -up Python-2.7.2/Include/methodobject.h.add-debug-malloc-stats Python-2.7.2/Include/methodobject.h
61 --- Python-2.7.2/Include/methodobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
62 +++ Python-2.7.2/Include/methodobject.h 2011-09-16 19:03:25.108821625 -0400
63 @@ -87,6 +87,10 @@ typedef struct {
64
65 PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
66
67 +PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
68 +PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
69 +
70 +
71 #ifdef __cplusplus
72 }
73 #endif
74 diff -up Python-2.7.2/Include/object.h.add-debug-malloc-stats Python-2.7.2/Include/object.h
75 --- Python-2.7.2/Include/object.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
76 +++ Python-2.7.2/Include/object.h 2011-09-16 19:03:25.108821625 -0400
77 @@ -980,6 +980,13 @@ PyAPI_DATA(PyObject *) _PyTrash_delete_l
78 _PyTrash_thread_deposit_object((PyObject*)op); \
79 } while (0);
80
81 +PyAPI_FUNC(void)
82 +_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
83 + size_t sizeof_block);
84 +
85 +PyAPI_FUNC(void)
86 +_PyObject_DebugTypeStats(FILE *out);
87 +
88 #ifdef __cplusplus
89 }
90 #endif
91 diff -up Python-2.7.2/Include/objimpl.h.add-debug-malloc-stats Python-2.7.2/Include/objimpl.h
92 --- Python-2.7.2/Include/objimpl.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
93 +++ Python-2.7.2/Include/objimpl.h 2011-09-16 19:03:25.108821625 -0400
94 @@ -101,13 +101,13 @@ PyAPI_FUNC(void) PyObject_Free(void *);
95
96 /* Macros */
97 #ifdef WITH_PYMALLOC
98 +PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out);
99 #ifdef PYMALLOC_DEBUG /* WITH_PYMALLOC && PYMALLOC_DEBUG */
100 PyAPI_FUNC(void *) _PyObject_DebugMalloc(size_t nbytes);
101 PyAPI_FUNC(void *) _PyObject_DebugRealloc(void *p, size_t nbytes);
102 PyAPI_FUNC(void) _PyObject_DebugFree(void *p);
103 PyAPI_FUNC(void) _PyObject_DebugDumpAddress(const void *p);
104 PyAPI_FUNC(void) _PyObject_DebugCheckAddress(const void *p);
105 -PyAPI_FUNC(void) _PyObject_DebugMallocStats(void);
106 PyAPI_FUNC(void *) _PyObject_DebugMallocApi(char api, size_t nbytes);
107 PyAPI_FUNC(void *) _PyObject_DebugReallocApi(char api, void *p, size_t nbytes);
108 PyAPI_FUNC(void) _PyObject_DebugFreeApi(char api, void *p);
109 diff -up Python-2.7.2/Include/stringobject.h.add-debug-malloc-stats Python-2.7.2/Include/stringobject.h
110 --- Python-2.7.2/Include/stringobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
111 +++ Python-2.7.2/Include/stringobject.h 2011-09-16 19:03:25.109821625 -0400
112 @@ -204,6 +204,8 @@ PyAPI_FUNC(PyObject *) _PyBytes_FormatAd
113 char *format_spec,
114 Py_ssize_t format_spec_len);
115
116 +PyAPI_FUNC(void) _PyString_DebugMallocStats(FILE *out);
117 +
118 #ifdef __cplusplus
119 }
120 #endif
121 diff -up Python-2.7.2/Include/unicodeobject.h.add-debug-malloc-stats Python-2.7.2/Include/unicodeobject.h
122 --- Python-2.7.2/Include/unicodeobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
123 +++ Python-2.7.2/Include/unicodeobject.h 2011-09-16 19:03:25.109821625 -0400
124 @@ -1406,6 +1406,8 @@ PyAPI_FUNC(int) _PyUnicode_IsAlpha(
125 Py_UNICODE ch /* Unicode character */
126 );
127
128 +PyAPI_FUNC(void) _PyUnicode_DebugMallocStats(FILE *out);
129 +
130 #ifdef __cplusplus
131 }
132 #endif
133 diff -up Python-2.7.2/Lib/test/test_sys.py.add-debug-malloc-stats Python-2.7.2/Lib/test/test_sys.py
134 --- Python-2.7.2/Lib/test/test_sys.py.add-debug-malloc-stats 2011-09-16 19:03:25.048821626 -0400
135 +++ Python-2.7.2/Lib/test/test_sys.py 2011-09-16 19:03:25.110821625 -0400
136 @@ -473,6 +473,32 @@ class SysModuleTest(unittest.TestCase):
137 p.wait()
138 self.assertIn(executable, ["''", repr(sys.executable)])
139
140 + def test_debugmallocstats(self):
141 + # Test sys._debugmallocstats()
142 +
143 + import subprocess
144 +
145 + # Verify the default of writing to stderr:
146 + p = subprocess.Popen([sys.executable,
147 + '-c', 'import sys; sys._debugmallocstats()'],
148 + stderr=subprocess.PIPE)
149 + out, err = p.communicate()
150 + p.wait()
151 + self.assertIn("arenas allocated current", err)
152 +
153 + # Verify that we can redirect the output to a file (not a file-like
154 + # object, though):
155 + with open('mallocstats.txt', 'w') as out:
156 + sys._debugmallocstats(out)
157 + result = open('mallocstats.txt').read()
158 + self.assertIn("arenas allocated current", result)
159 + os.unlink('mallocstats.txt')
160 +
161 + # Verify that the destination must be a file:
162 + with self.assertRaises(TypeError):
163 + sys._debugmallocstats(42)
164 +
165 +
166 @test.test_support.cpython_only
167 class SizeofTest(unittest.TestCase):
168
169 diff -up Python-2.7.2/Objects/classobject.c.add-debug-malloc-stats Python-2.7.2/Objects/classobject.c
170 --- Python-2.7.2/Objects/classobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
171 +++ Python-2.7.2/Objects/classobject.c 2011-09-16 19:03:25.110821625 -0400
172 @@ -2670,3 +2670,12 @@ PyMethod_Fini(void)
173 {
174 (void)PyMethod_ClearFreeList();
175 }
176 +
177 +/* Print summary info about the state of the optimized allocator */
178 +void
179 +_PyMethod_DebugMallocStats(FILE *out)
180 +{
181 + _PyDebugAllocatorStats(out,
182 + "free PyMethodObject",
183 + numfree, sizeof(PyMethodObject));
184 +}
185 diff -up Python-2.7.2/Objects/dictobject.c.add-debug-malloc-stats Python-2.7.2/Objects/dictobject.c
186 --- Python-2.7.2/Objects/dictobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
187 +++ Python-2.7.2/Objects/dictobject.c 2011-09-16 19:03:25.111821625 -0400
188 @@ -225,6 +225,15 @@ show_track(void)
189 static PyDictObject *free_list[PyDict_MAXFREELIST];
190 static int numfree = 0;
191
192 +/* Print summary info about the state of the optimized allocator */
193 +void
194 +_PyDict_DebugMallocStats(FILE *out)
195 +{
196 + _PyDebugAllocatorStats(out,
197 + "free PyDictObject", numfree, sizeof(PyDictObject));
198 +}
199 +
200 +
201 void
202 PyDict_Fini(void)
203 {
204 diff -up Python-2.7.2/Objects/floatobject.c.add-debug-malloc-stats Python-2.7.2/Objects/floatobject.c
205 --- Python-2.7.2/Objects/floatobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
206 +++ Python-2.7.2/Objects/floatobject.c 2011-09-16 19:03:25.111821625 -0400
207 @@ -35,6 +35,22 @@ typedef struct _floatblock PyFloatBlock;
208 static PyFloatBlock *block_list = NULL;
209 static PyFloatObject *free_list = NULL;
210
211 +/* Print summary info about the state of the optimized allocator */
212 +void
213 +_PyFloat_DebugMallocStats(FILE *out)
214 +{
215 + int num_blocks = 0;
216 + PyFloatBlock *block;
217 +
218 + /* Walk the block list, counting */
219 + for (block = block_list; block ; block = block->next) {
220 + num_blocks++;
221 + }
222 +
223 + _PyDebugAllocatorStats(out,
224 + "PyFloatBlock", num_blocks, sizeof(PyFloatBlock));
225 +}
226 +
227 static PyFloatObject *
228 fill_free_list(void)
229 {
230 diff -up Python-2.7.2/Objects/frameobject.c.add-debug-malloc-stats Python-2.7.2/Objects/frameobject.c
231 --- Python-2.7.2/Objects/frameobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
232 +++ Python-2.7.2/Objects/frameobject.c 2011-09-16 19:03:25.112821625 -0400
233 @@ -980,3 +980,13 @@ PyFrame_Fini(void)
234 Py_XDECREF(builtin_object);
235 builtin_object = NULL;
236 }
237 +
238 +/* Print summary info about the state of the optimized allocator */
239 +void
240 +_PyFrame_DebugMallocStats(FILE *out)
241 +{
242 + _PyDebugAllocatorStats(out,
243 + "free PyFrameObject",
244 + numfree, sizeof(PyFrameObject));
245 +}
246 +
247 diff -up Python-2.7.2/Objects/intobject.c.add-debug-malloc-stats Python-2.7.2/Objects/intobject.c
248 --- Python-2.7.2/Objects/intobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
249 +++ Python-2.7.2/Objects/intobject.c 2011-09-16 19:03:25.112821625 -0400
250 @@ -44,6 +44,23 @@ typedef struct _intblock PyIntBlock;
251 static PyIntBlock *block_list = NULL;
252 static PyIntObject *free_list = NULL;
253
254 +
255 +/* Print summary info about the state of the optimized allocator */
256 +void
257 +_PyInt_DebugMallocStats(FILE *out)
258 +{
259 + int num_blocks = 0;
260 + PyIntBlock *block;
261 +
262 + /* Walk the block list, counting */
263 + for (block = block_list; block ; block = block->next) {
264 + num_blocks++;
265 + }
266 +
267 + _PyDebugAllocatorStats(out,
268 + "PyIntBlock", num_blocks, sizeof(PyIntBlock));
269 +}
270 +
271 static PyIntObject *
272 fill_free_list(void)
273 {
274 diff -up Python-2.7.2/Objects/listobject.c.add-debug-malloc-stats Python-2.7.2/Objects/listobject.c
275 --- Python-2.7.2/Objects/listobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
276 +++ Python-2.7.2/Objects/listobject.c 2011-09-16 19:03:25.113821625 -0400
277 @@ -109,6 +109,15 @@ PyList_Fini(void)
278 }
279 }
280
281 +/* Print summary info about the state of the optimized allocator */
282 +void
283 +_PyList_DebugMallocStats(FILE *out)
284 +{
285 + _PyDebugAllocatorStats(out,
286 + "free PyListObject",
287 + numfree, sizeof(PyListObject));
288 +}
289 +
290 PyObject *
291 PyList_New(Py_ssize_t size)
292 {
293 diff -up Python-2.7.2/Objects/methodobject.c.add-debug-malloc-stats Python-2.7.2/Objects/methodobject.c
294 --- Python-2.7.2/Objects/methodobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
295 +++ Python-2.7.2/Objects/methodobject.c 2011-09-16 19:03:25.113821625 -0400
296 @@ -412,6 +412,15 @@ PyCFunction_Fini(void)
297 (void)PyCFunction_ClearFreeList();
298 }
299
300 +/* Print summary info about the state of the optimized allocator */
301 +void
302 +_PyCFunction_DebugMallocStats(FILE *out)
303 +{
304 + _PyDebugAllocatorStats(out,
305 + "free PyCFunction",
306 + numfree, sizeof(PyCFunction));
307 +}
308 +
309 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
310 but it's part of the API so we need to keep a function around that
311 existing C extensions can call.
312 diff -up Python-2.7.2/Objects/object.c.add-debug-malloc-stats Python-2.7.2/Objects/object.c
313 --- Python-2.7.2/Objects/object.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
314 +++ Python-2.7.2/Objects/object.c 2011-09-16 19:04:46.463820849 -0400
315 @@ -2334,6 +2334,23 @@ PyMem_Free(void *p)
316 PyMem_FREE(p);
317 }
318
319 +void
320 +_PyObject_DebugTypeStats(FILE *out)
321 +{
322 + _PyString_DebugMallocStats(out);
323 + _PyCFunction_DebugMallocStats(out);
324 + _PyDict_DebugMallocStats(out);
325 + _PyFloat_DebugMallocStats(out);
326 + _PyFrame_DebugMallocStats(out);
327 + _PyInt_DebugMallocStats(out);
328 + _PyList_DebugMallocStats(out);
329 + _PyMethod_DebugMallocStats(out);
330 + _PySet_DebugMallocStats(out);
331 + _PyTuple_DebugMallocStats(out);
332 +#if Py_USING_UNICODE
333 + _PyUnicode_DebugMallocStats(out);
334 +#endif
335 +}
336
337 /* These methods are used to control infinite recursion in repr, str, print,
338 etc. Container objects that may recursively contain themselves,
339 diff -up Python-2.7.2/Objects/obmalloc.c.add-debug-malloc-stats Python-2.7.2/Objects/obmalloc.c
340 --- Python-2.7.2/Objects/obmalloc.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
341 +++ Python-2.7.2/Objects/obmalloc.c 2011-09-16 19:03:25.114821625 -0400
342 @@ -508,12 +508,10 @@ static struct arena_object* usable_arena
343 /* Number of arenas allocated that haven't been free()'d. */
344 static size_t narenas_currently_allocated = 0;
345
346 -#ifdef PYMALLOC_DEBUG
347 /* Total number of times malloc() called to allocate an arena. */
348 static size_t ntimes_arena_allocated = 0;
349 /* High water mark (max value ever seen) for narenas_currently_allocated. */
350 static size_t narenas_highwater = 0;
351 -#endif
352
353 /* Allocate a new arena. If we run out of memory, return NULL. Else
354 * allocate a new arena, and return the address of an arena_object
355 @@ -528,7 +526,7 @@ new_arena(void)
356
357 #ifdef PYMALLOC_DEBUG
358 if (Py_GETENV("PYTHONMALLOCSTATS"))
359 - _PyObject_DebugMallocStats();
360 + _PyObject_DebugMallocStats(stderr);
361 #endif
362 if (unused_arena_objects == NULL) {
363 uint i;
364 @@ -588,11 +586,9 @@ new_arena(void)
365 arenaobj->address = (uptr)address;
366
367 ++narenas_currently_allocated;
368 -#ifdef PYMALLOC_DEBUG
369 ++ntimes_arena_allocated;
370 if (narenas_currently_allocated > narenas_highwater)
371 narenas_highwater = narenas_currently_allocated;
372 -#endif
373 arenaobj->freepools = NULL;
374 /* pool_address <- first pool-aligned address in the arena
375 nfreepools <- number of whole pools that fit after alignment */
376 @@ -1694,17 +1690,19 @@ _PyObject_DebugDumpAddress(const void *p
377 }
378 }
379
380 +#endif /* PYMALLOC_DEBUG */
381 +
382 static size_t
383 -printone(const char* msg, size_t value)
384 +printone(FILE *out, const char* msg, size_t value)
385 {
386 int i, k;
387 char buf[100];
388 size_t origvalue = value;
389
390 - fputs(msg, stderr);
391 + fputs(msg, out);
392 for (i = (int)strlen(msg); i < 35; ++i)
393 - fputc(' ', stderr);
394 - fputc('=', stderr);
395 + fputc(' ', out);
396 + fputc('=', out);
397
398 /* Write the value with commas. */
399 i = 22;
400 @@ -1725,17 +1723,32 @@ printone(const char* msg, size_t value)
401
402 while (i >= 0)
403 buf[i--] = ' ';
404 - fputs(buf, stderr);
405 + fputs(buf, out);
406
407 return origvalue;
408 }
409
410 -/* Print summary info to stderr about the state of pymalloc's structures.
411 +void
412 +_PyDebugAllocatorStats(FILE *out,
413 + const char *block_name, int num_blocks, size_t sizeof_block)
414 +{
415 + char buf1[128];
416 + char buf2[128];
417 + PyOS_snprintf(buf1, sizeof(buf1),
418 + "%d %ss * %zd bytes each",
419 + num_blocks, block_name, sizeof_block);
420 + PyOS_snprintf(buf2, sizeof(buf2),
421 + "%48s ", buf1);
422 + (void)printone(out, buf2, num_blocks * sizeof_block);
423 +}
424 +
425 +
426 +/* Print summary info to "out" about the state of pymalloc's structures.
427 * In Py_DEBUG mode, also perform some expensive internal consistency
428 * checks.
429 */
430 void
431 -_PyObject_DebugMallocStats(void)
432 +_PyObject_DebugMallocStats(FILE *out)
433 {
434 uint i;
435 const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
436 @@ -1764,7 +1777,7 @@ _PyObject_DebugMallocStats(void)
437 size_t total;
438 char buf[128];
439
440 - fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
441 + fprintf(out, "Small block threshold = %d, in %u size classes.\n",
442 SMALL_REQUEST_THRESHOLD, numclasses);
443
444 for (i = 0; i < numclasses; ++i)
445 @@ -1818,10 +1831,10 @@ _PyObject_DebugMallocStats(void)
446 }
447 assert(narenas == narenas_currently_allocated);
448
449 - fputc('\n', stderr);
450 + fputc('\n', out);
451 fputs("class size num pools blocks in use avail blocks\n"
452 "----- ---- --------- ------------- ------------\n",
453 - stderr);
454 + out);
455
456 for (i = 0; i < numclasses; ++i) {
457 size_t p = numpools[i];
458 @@ -1832,7 +1845,7 @@ _PyObject_DebugMallocStats(void)
459 assert(b == 0 && f == 0);
460 continue;
461 }
462 - fprintf(stderr, "%5u %6u "
463 + fprintf(out, "%5u %6u "
464 "%11" PY_FORMAT_SIZE_T "u "
465 "%15" PY_FORMAT_SIZE_T "u "
466 "%13" PY_FORMAT_SIZE_T "u\n",
467 @@ -1842,36 +1855,35 @@ _PyObject_DebugMallocStats(void)
468 pool_header_bytes += p * POOL_OVERHEAD;
469 quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
470 }
471 - fputc('\n', stderr);
472 - (void)printone("# times object malloc called", serialno);
473 -
474 - (void)printone("# arenas allocated total", ntimes_arena_allocated);
475 - (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
476 - (void)printone("# arenas highwater mark", narenas_highwater);
477 - (void)printone("# arenas allocated current", narenas);
478 + fputc('\n', out);
479 +#ifdef PYMALLOC_DEBUG
480 + (void)printone(out, "# times object malloc called", serialno);
481 +#endif
482 + (void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
483 + (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
484 + (void)printone(out, "# arenas highwater mark", narenas_highwater);
485 + (void)printone(out, "# arenas allocated current", narenas);
486
487 PyOS_snprintf(buf, sizeof(buf),
488 "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
489 narenas, ARENA_SIZE);
490 - (void)printone(buf, narenas * ARENA_SIZE);
491 + (void)printone(out, buf, narenas * ARENA_SIZE);
492
493 - fputc('\n', stderr);
494 + fputc('\n', out);
495
496 - total = printone("# bytes in allocated blocks", allocated_bytes);
497 - total += printone("# bytes in available blocks", available_bytes);
498 + total = printone(out, "# bytes in allocated blocks", allocated_bytes);
499 + total += printone(out, "# bytes in available blocks", available_bytes);
500
501 PyOS_snprintf(buf, sizeof(buf),
502 "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
503 - total += printone(buf, (size_t)numfreepools * POOL_SIZE);
504 + total += printone(out, buf, (size_t)numfreepools * POOL_SIZE);
505
506 - total += printone("# bytes lost to pool headers", pool_header_bytes);
507 - total += printone("# bytes lost to quantization", quantization);
508 - total += printone("# bytes lost to arena alignment", arena_alignment);
509 - (void)printone("Total", total);
510 + total += printone(out, "# bytes lost to pool headers", pool_header_bytes);
511 + total += printone(out, "# bytes lost to quantization", quantization);
512 + total += printone(out, "# bytes lost to arena alignment", arena_alignment);
513 + (void)printone(out, "Total", total);
514 }
515
516 -#endif /* PYMALLOC_DEBUG */
517 -
518 #ifdef Py_USING_MEMORY_DEBUGGER
519 /* Make this function last so gcc won't inline it since the definition is
520 * after the reference.
521 diff -up Python-2.7.2/Objects/setobject.c.add-debug-malloc-stats Python-2.7.2/Objects/setobject.c
522 --- Python-2.7.2/Objects/setobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
523 +++ Python-2.7.2/Objects/setobject.c 2011-09-16 19:03:25.115821625 -0400
524 @@ -1088,6 +1088,16 @@ PySet_Fini(void)
525 Py_CLEAR(emptyfrozenset);
526 }
527
528 +/* Print summary info about the state of the optimized allocator */
529 +void
530 +_PySet_DebugMallocStats(FILE *out)
531 +{
532 + _PyDebugAllocatorStats(out,
533 + "free PySetObject",
534 + numfree, sizeof(PySetObject));
535 +}
536 +
537 +
538 static PyObject *
539 set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
540 {
541 diff -up Python-2.7.2/Objects/stringobject.c.add-debug-malloc-stats Python-2.7.2/Objects/stringobject.c
542 --- Python-2.7.2/Objects/stringobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
543 +++ Python-2.7.2/Objects/stringobject.c 2011-09-16 19:03:25.116821625 -0400
544 @@ -4822,3 +4822,43 @@ void _Py_ReleaseInternedStrings(void)
545 PyDict_Clear(interned);
546 Py_CLEAR(interned);
547 }
548 +
549 +void _PyString_DebugMallocStats(FILE *out)
550 +{
551 + ssize_t i;
552 + int num_immortal = 0, num_mortal = 0;
553 + ssize_t immortal_size = 0, mortal_size = 0;
554 +
555 + if (interned == NULL || !PyDict_Check(interned))
556 + return;
557 +
558 + for (i = 0; i <= ((PyDictObject*)interned)->ma_mask; i++) {
559 + PyDictEntry *ep = ((PyDictObject*)interned)->ma_table + i;
560 + PyObject *pvalue = ep->me_value;
561 + if (pvalue != NULL) {
562 + PyStringObject *s = (PyStringObject *)ep->me_key;
563 +
564 + switch (s->ob_sstate) {
565 + case SSTATE_NOT_INTERNED:
566 + /* XXX Shouldn't happen */
567 + break;
568 + case SSTATE_INTERNED_IMMORTAL:
569 + num_immortal ++;
570 + immortal_size += s->ob_size;
571 + break;
572 + case SSTATE_INTERNED_MORTAL:
573 + num_mortal ++;
574 + mortal_size += s->ob_size;
575 + break;
576 + default:
577 + Py_FatalError("Inconsistent interned string state.");
578 + }
579 + }
580 + }
581 +
582 + fprintf(out, "%d mortal interned strings\n", num_mortal);
583 + fprintf(out, "%d immortal interned strings\n", num_immortal);
584 + fprintf(out, "total size of all interned strings: "
585 + "%zi/%zi "
586 + "mortal/immortal\n", mortal_size, immortal_size);
587 +}
588 diff -up Python-2.7.2/Objects/tupleobject.c.add-debug-malloc-stats Python-2.7.2/Objects/tupleobject.c
589 --- Python-2.7.2/Objects/tupleobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
590 +++ Python-2.7.2/Objects/tupleobject.c 2011-09-16 19:03:25.116821625 -0400
591 @@ -44,6 +44,22 @@ show_track(void)
592 }
593 #endif
594
595 +/* Print summary info about the state of the optimized allocator */
596 +void
597 +_PyTuple_DebugMallocStats(FILE *out)
598 +{
599 +#if PyTuple_MAXSAVESIZE > 0
600 + int i;
601 + char buf[128];
602 + for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
603 + PyOS_snprintf(buf, sizeof(buf),
604 + "free %d-sized PyTupleObject", i);
605 + _PyDebugAllocatorStats(out,
606 + buf,
607 + numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i));
608 + }
609 +#endif
610 +}
611
612 PyObject *
613 PyTuple_New(register Py_ssize_t size)
614 diff -up Python-2.7.2/Objects/unicodeobject.c.add-debug-malloc-stats Python-2.7.2/Objects/unicodeobject.c
615 --- Python-2.7.2/Objects/unicodeobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
616 +++ Python-2.7.2/Objects/unicodeobject.c 2011-09-16 19:03:25.118821625 -0400
617 @@ -8883,6 +8883,12 @@ _PyUnicode_Fini(void)
618 (void)PyUnicode_ClearFreeList();
619 }
620
621 +void _PyUnicode_DebugMallocStats(FILE *out)
622 +{
623 + _PyDebugAllocatorStats(out, "free PyUnicodeObject", numfree,
624 + sizeof(PyUnicodeObject));
625 +}
626 +
627 #ifdef __cplusplus
628 }
629 #endif
630 diff -up Python-2.7.2/Python/pythonrun.c.add-debug-malloc-stats Python-2.7.2/Python/pythonrun.c
631 --- Python-2.7.2/Python/pythonrun.c.add-debug-malloc-stats 2011-09-16 19:03:25.025821626 -0400
632 +++ Python-2.7.2/Python/pythonrun.c 2011-09-16 19:03:25.118821625 -0400
633 @@ -549,7 +549,7 @@ Py_Finalize(void)
634 #endif /* Py_TRACE_REFS */
635 #ifdef PYMALLOC_DEBUG
636 if (Py_GETENV("PYTHONMALLOCSTATS"))
637 - _PyObject_DebugMallocStats();
638 + _PyObject_DebugMallocStats(stderr);
639 #endif
640
641 call_ll_exitfuncs();
642 diff -up Python-2.7.2/Python/sysmodule.c.add-debug-malloc-stats Python-2.7.2/Python/sysmodule.c
643 --- Python-2.7.2/Python/sysmodule.c.add-debug-malloc-stats 2011-09-16 19:03:25.007821626 -0400
644 +++ Python-2.7.2/Python/sysmodule.c 2011-09-16 19:03:25.119821625 -0400
645 @@ -872,6 +872,57 @@ a 11-tuple where the entries in the tupl
646 extern "C" {
647 #endif
648
649 +static PyObject *
650 +sys_debugmallocstats(PyObject *self, PyObject *args)
651 +{
652 + PyObject *file = NULL;
653 + FILE *fp;
654 +
655 + if (!PyArg_ParseTuple(args, "|O!",
656 + &PyFile_Type, &file)) {
657 + return NULL;
658 + }
659 + if (!file) {
660 + /* Default to sys.stderr: */
661 + file = PySys_GetObject("stderr");
662 + if (!file) {
663 + PyErr_SetString(PyExc_ValueError, "sys.stderr not set");
664 + return NULL;
665 + }
666 + if (!PyFile_Check(file)) {
667 + PyErr_SetString(PyExc_TypeError, "sys.stderr is not a file");
668 + return NULL;
669 + }
670 + }
671 +
672 + Py_INCREF(file);
673 + /* OK, we now own a ref on non-NULL "file" */
674 +
675 + fp = PyFile_AsFile(file);
676 + if (!fp) {
677 + PyErr_SetString(PyExc_ValueError, "file is closed");
678 + Py_DECREF(file);
679 + return NULL;
680 + }
681 +
682 + _PyObject_DebugMallocStats(fp);
683 + fputc('\n', fp);
684 + _PyObject_DebugTypeStats(fp);
685 +
686 + Py_DECREF(file);
687 +
688 + Py_RETURN_NONE;
689 +}
690 +PyDoc_STRVAR(debugmallocstats_doc,
691 +"_debugmallocstats([file])\n\
692 +\n\
693 +Print summary info to the given file (or sys.stderr) about the state of\n\
694 +pymalloc's structures.\n\
695 +\n\
696 +In Py_DEBUG mode, also perform some expensive internal consistency\n\
697 +checks.\n\
698 +");
699 +
700 #ifdef Py_TRACE_REFS
701 /* Defined in objects.c because it uses static globals if that file */
702 extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
703 @@ -970,6 +1021,8 @@ static PyMethodDef sys_methods[] = {
704 {"settrace", sys_settrace, METH_O, settrace_doc},
705 {"gettrace", sys_gettrace, METH_NOARGS, gettrace_doc},
706 {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
707 + {"_debugmallocstats", sys_debugmallocstats, METH_VARARGS,
708 + debugmallocstats_doc},
709 {NULL, NULL} /* sentinel */
710 };
711