summaryrefslogtreecommitdiffstats
path: root/Objects/obmalloc.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2002-04-01 06:04:21 (GMT)
committerTim Peters <tim.peters@gmail.com>2002-04-01 06:04:21 (GMT)
commit7ccfadf3a88fb83ffa9cee2a3ff41910aa5a00ec (patch)
tree14fe0231a6e07c427226303d6105c77262b25464 /Objects/obmalloc.c
parentde14a30d1d70073d36f207fe432e4adad5178399 (diff)
downloadcpython-7ccfadf3a88fb83ffa9cee2a3ff41910aa5a00ec.zip
cpython-7ccfadf3a88fb83ffa9cee2a3ff41910aa5a00ec.tar.gz
cpython-7ccfadf3a88fb83ffa9cee2a3ff41910aa5a00ec.tar.bz2
New PYMALLOC_DEBUG function void _PyMalloc_DebugDumpStats(void).
This displays stats about the # of arenas, pools, blocks and bytes, to stderr, both used and reserved but unused. CAUTION: Because PYMALLOC_DEBUG is on, the debug malloc routine adds 16 bytes to each request. This makes each block appear two size classes higher than it would be if PYMALLOC_DEBUG weren't on. So far, playing with this confirms the obvious: there's a lot of activity in the "small dict" size class, but nothing in the core makes any use of the 8-byte or 16-byte classes.
Diffstat (limited to 'Objects/obmalloc.c')
-rw-r--r--Objects/obmalloc.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index cf2b477..3030844 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -1026,7 +1026,11 @@ _PyMalloc_DebugRealloc(void *p, size_t nbytes)
return fresh;
}
-void
+/* Check the forbidden bytes on both ends of the memory allocated for p.
+ * If anything is wrong, print info to stderr via _PyMalloc_DebugDumpAddress,
+ * and call Py_FatalError to kill the program.
+ */
+ void
_PyMalloc_DebugCheckAddress(const void *p)
{
const uchar *q = (const uchar *)p;
@@ -1063,6 +1067,7 @@ error:
Py_FatalError(msg);
}
+/* Display info to stderr about the memory block at p. */
void
_PyMalloc_DebugDumpAddress(const void *p)
{
@@ -1149,4 +1154,95 @@ _PyMalloc_DebugDumpAddress(const void *p)
}
}
+/* Print summary info to stderr about the state of pymalloc's structures. */
+void
+_PyMalloc_DebugDumpStats(void)
+{
+ uint i;
+ const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
+ uint numfreepools = 0;
+ /* # of pools per class index */
+ ulong numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
+ /* # of allocated blocks per class index */
+ ulong numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
+ /* # of free blocks per class index */
+ ulong numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
+ ulong grandtotal; /* total # of allocated bytes */
+ ulong freegrandtotal; /* total # of available bytes in used blocks */
+
+ fprintf(stderr, "%u arenas * %d bytes/arena = %lu total bytes.\n",
+ narenas, ARENA_SIZE, narenas * (ulong)ARENA_SIZE);
+ fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
+ SMALL_REQUEST_THRESHOLD, numclasses);
+ fprintf(stderr, "pymalloc malloc+realloc called %lu times.\n",
+ serialno);
+
+ for (i = 0; i < numclasses; ++i)
+ numpools[i] = numblocks[i] = numfreeblocks[i] = 0;
+
+ /* Because empty pools aren't linked to from anything, it's easiest
+ * to march over all the arenas.
+ */
+ for (i = 0; i < narenas; ++i) {
+ uint poolsinarena;
+ uint j;
+ uptr base = arenas[i];
+
+ /* round up to pool alignment */
+ poolsinarena = ARENA_SIZE / POOL_SIZE;
+ if (base & (uptr)POOL_SIZE_MASK) {
+ --poolsinarena;
+ base &= ~(uptr)POOL_SIZE_MASK;
+ base += POOL_SIZE;
+ }
+
+ if (i == narenas - 1) {
+ /* current arena may have raw memory at the end */
+ numfreepools += nfreepools;
+ poolsinarena -= nfreepools;
+ }
+
+ /* visit every pool in the arena */
+ for (j = 0; j < poolsinarena; ++j, base += POOL_SIZE) {
+ poolp p = (poolp)base;
+ if (p->ref.count == 0) {
+ /* currently unused */
+ ++numfreepools;
+ continue;
+ }
+ ++numpools[p->szidx];
+ numblocks[p->szidx] += p->ref.count;
+ numfreeblocks[p->szidx] += p->capacity - p->ref.count;
+ }
+ }
+
+ fputc('\n', stderr);
+ fprintf(stderr, "Number of unused pools: %u\n", numfreepools);
+ fputc('\n', stderr);
+ fputs("class num bytes num pools blocks in use avail blocks\n"
+ "----- --------- --------- ------------- ------------\n",
+ stderr);
+
+ grandtotal = freegrandtotal = 0;
+ for (i = 0; i < numclasses; ++i) {
+ ulong p = numpools[i];
+ ulong b = numblocks[i];
+ ulong f = numfreeblocks[i];
+ uint size = (i+1) << ALIGNMENT_SHIFT;
+ if (p == 0) {
+ assert(b == 0 && f == 0);
+ continue;
+ }
+ fprintf(stderr, "%5u %11u %11lu %15lu %13lu\n",
+ i, size, p, b, f);
+ grandtotal += b * size;
+ freegrandtotal += f * size;
+ }
+ fputc('\n', stderr);
+ fprintf(stderr, "Total bytes in allocated blocks: %lu\n",
+ grandtotal);
+ fprintf(stderr, "Total free bytes in used pools: %lu\n",
+ freegrandtotal);
+}
+
#endif /* PYMALLOC_DEBUG */