@@ -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. */
11991211void
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