Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 16bcb6b

Browse files
committed
_PyMalloc_DebugDumpStats(): vastly improved the output, and it now
accounts for every byte.
1 parent e70ddf3 commit 16bcb6b

1 file changed

Lines changed: 58 additions & 21 deletions

File tree

Objects/obmalloc.c

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,8 @@ typedef struct pool_header *poolp;
252252
/* Round pointer P down to the closest pool-aligned address <= P, as a poolp */
253253
#define POOL_ADDR(P) ((poolp)((uptr)(P) & ~(uptr)POOL_SIZE_MASK))
254254

255-
/* Return total number of blocks in poolp P, as a uint. */
256-
#define NUMBLOCKS(P) \
257-
((uint)(POOL_SIZE - POOL_OVERHEAD) / INDEX2SIZE((P)->szidx))
255+
/* Return total number of blocks in pool of size index I, as a uint. */
256+
#define NUMBLOCKS(I) ((uint)(POOL_SIZE - POOL_OVERHEAD) / INDEX2SIZE(I))
258257

259258
/*==========================================================================*/
260259

@@ -1195,24 +1194,48 @@ _PyMalloc_DebugDumpAddress(const void *p)
11951194
}
11961195
}
11971196

1197+
static ulong
1198+
printone(const char* msg, ulong value)
1199+
{
1200+
const size_t len = strlen(msg);
1201+
size_t i;
1202+
1203+
fputs(msg, stderr);
1204+
for (i = len; i < 40; ++i)
1205+
fputc(' ', stderr);
1206+
fprintf(stderr, "= %15lu\n", value);
1207+
return value;
1208+
}
1209+
11981210
/* Print summary info to stderr about the state of pymalloc's structures. */
11991211
void
12001212
_PyMalloc_DebugDumpStats(void)
12011213
{
12021214
uint i;
12031215
const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
1204-
uint numfreepools = 0;
1205-
/* # of pools per class index */
1216+
/* # of pools, allocated blocks, and free blocks per class index */
12061217
ulong numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
1207-
/* # of allocated blocks per class index */
12081218
ulong numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
1209-
/* # of free blocks per class index */
12101219
ulong numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
1211-
ulong grandtotal; /* total # of allocated bytes */
1212-
ulong freegrandtotal; /* total # of available bytes in used pools */
1220+
/* total # of allocated bytes in used and full pools */
1221+
ulong allocated_bytes = 0;
1222+
/* total # of available bytes in used pools */
1223+
ulong available_bytes = 0;
1224+
/* # of free pools + pools not yet carved out of current arena */
1225+
uint numfreepools = 0;
1226+
/* # of bytes for arena alignment padding */
1227+
uint arena_alignment = 0;
1228+
/* # of bytes in used and full pools used for pool_headers */
1229+
ulong pool_header_bytes = 0;
1230+
/* # of bytes in used and full pools wasted due to quantization,
1231+
* i.e. the necessarily leftover space at the ends of used and
1232+
* full pools.
1233+
*/
1234+
ulong quantization = 0;
1235+
/* running total -- should equal narenas * ARENA_SIZE */
1236+
ulong total;
1237+
char buf[128];
12131238

1214-
fprintf(stderr, "%u arenas * %d bytes/arena = %lu total bytes.\n",
1215-
narenas, ARENA_SIZE, narenas * (ulong)ARENA_SIZE);
12161239
fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
12171240
SMALL_REQUEST_THRESHOLD, numclasses);
12181241
fprintf(stderr, "pymalloc malloc+realloc called %lu times.\n",
@@ -1234,6 +1257,7 @@ _PyMalloc_DebugDumpStats(void)
12341257
poolsinarena = ARENA_SIZE / POOL_SIZE;
12351258
if (base & (uptr)POOL_SIZE_MASK) {
12361259
--poolsinarena;
1260+
arena_alignment += POOL_SIZE;
12371261
base &= ~(uptr)POOL_SIZE_MASK;
12381262
base += POOL_SIZE;
12391263
}
@@ -1254,18 +1278,16 @@ _PyMalloc_DebugDumpStats(void)
12541278
}
12551279
++numpools[p->szidx];
12561280
numblocks[p->szidx] += p->ref.count;
1257-
numfreeblocks[p->szidx] += NUMBLOCKS(p) - p->ref.count;
1281+
numfreeblocks[p->szidx] += NUMBLOCKS(p->szidx) -
1282+
p->ref.count;
12581283
}
12591284
}
12601285

1261-
fputc('\n', stderr);
1262-
fprintf(stderr, "Number of unused pools: %u\n", numfreepools);
12631286
fputc('\n', stderr);
12641287
fputs("class num bytes num pools blocks in use avail blocks\n"
12651288
"----- --------- --------- ------------- ------------\n",
12661289
stderr);
12671290

1268-
grandtotal = freegrandtotal = 0;
12691291
for (i = 0; i < numclasses; ++i) {
12701292
ulong p = numpools[i];
12711293
ulong b = numblocks[i];
@@ -1277,14 +1299,29 @@ _PyMalloc_DebugDumpStats(void)
12771299
}
12781300
fprintf(stderr, "%5u %11u %11lu %15lu %13lu\n",
12791301
i, size, p, b, f);
1280-
grandtotal += b * size;
1281-
freegrandtotal += f * size;
1302+
allocated_bytes += b * size;
1303+
available_bytes += f * size;
1304+
pool_header_bytes += p * POOL_OVERHEAD;
1305+
quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
12821306
}
12831307
fputc('\n', stderr);
1284-
fprintf(stderr, "Total bytes in allocated blocks: %lu\n",
1285-
grandtotal);
1286-
fprintf(stderr, "Total free bytes in used pools: %lu\n",
1287-
freegrandtotal);
1308+
1309+
PyOS_snprintf(buf, sizeof(buf),
1310+
"%u arenas * %d bytes/arena", narenas, ARENA_SIZE);
1311+
(void)printone(buf, (ulong)narenas * ARENA_SIZE);
1312+
1313+
fputc('\n', stderr);
1314+
1315+
PyOS_snprintf(buf, sizeof(buf),
1316+
"%u unused pools * %d bytes", numfreepools, POOL_SIZE);
1317+
total = printone(buf, (ulong)numfreepools * POOL_SIZE);
1318+
1319+
total += printone("# bytes in allocated blocks", allocated_bytes);
1320+
total += printone("# bytes in available blocks", available_bytes);
1321+
total += printone("# bytes lost to pool headers", pool_header_bytes);
1322+
total += printone("# bytes lost to quantization", quantization);
1323+
total += printone("# bytes lost to arena alignment", arena_alignment);
1324+
(void)printone("Total", total);
12881325
}
12891326

12901327
#endif /* PYMALLOC_DEBUG */

0 commit comments

Comments
 (0)