Skip to content

Commit 0c318b1

Browse files
committed
Output some stats on the allocator
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags:
1 parent 8197d5f commit 0c318b1

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

Objects/obmalloc.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <stdbool.h>
1313
#ifdef WITH_MIMALLOC
1414
#include "mimalloc.h"
15+
#include "mimalloc/internal.h" // for stats
1516
#endif
1617

1718
#undef uint
@@ -2708,6 +2709,29 @@ pool_is_in_list(const poolp target, poolp list)
27082709
}
27092710
#endif
27102711

2712+
#ifdef WITH_MIMALLOC
2713+
struct _alloc_stats {
2714+
size_t allocated_blocks;
2715+
size_t allocated_bytes;
2716+
size_t allocated_with_overhead;
2717+
size_t bytes_reserved;
2718+
size_t bytes_committed;
2719+
};
2720+
2721+
static bool _collect_alloc_stats(
2722+
const mi_heap_t* heap, const mi_heap_area_t* area,
2723+
void* block, size_t block_size, void* arg)
2724+
{
2725+
struct _alloc_stats *stats = (struct _alloc_stats *)arg;
2726+
stats->allocated_blocks += area->used;
2727+
stats->allocated_bytes += area->used * area->block_size;
2728+
stats->allocated_with_overhead += area->used * area->full_block_size;
2729+
stats->bytes_reserved += area->reserved;
2730+
stats->bytes_committed += area->committed;
2731+
return 1;
2732+
}
2733+
#endif
2734+
27112735
/* Print summary info to "out" about the state of pymalloc's structures.
27122736
* In Py_DEBUG mode, also perform some expensive internal consistency
27132737
* checks.
@@ -2718,6 +2742,46 @@ pool_is_in_list(const poolp target, poolp list)
27182742
int
27192743
_PyObject_DebugMallocStats(FILE *out)
27202744
{
2745+
#ifdef WITH_MIMALLOC
2746+
if (_PyMem_MimallocEnabled()) {
2747+
fprintf(out, "Small block threshold = %ld, in %u size classes.\n",
2748+
MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE);
2749+
fprintf(out, "Medium block threshold = %ld\n",
2750+
MI_MEDIUM_OBJ_SIZE_MAX);
2751+
fprintf(out, "Large object max size = %ld\n",
2752+
MI_LARGE_OBJ_SIZE_MAX);
2753+
2754+
PyThreadState *tstate = PyInterpreterState_ThreadHead(PyThreadState_GetInterpreter(PyThreadState_Get()));
2755+
struct _alloc_stats stats[MI_NUM_HEAPS] = {};
2756+
mi_heap_tag_t tags[] = {
2757+
mi_heap_tag_default,
2758+
mi_heap_tag_obj,
2759+
};
2760+
while (tstate != NULL) {
2761+
for (size_t i = 0; i != sizeof(tags)/sizeof(*tags); i++) {
2762+
mi_heap_t *heap = tstate->heaps[i];
2763+
mi_heap_visit_blocks(heap, false, &_collect_alloc_stats, &stats[i]);
2764+
}
2765+
tstate = PyThreadState_Next(tstate);
2766+
}
2767+
2768+
2769+
for (size_t i = 0; i != sizeof(tags)/sizeof(*tags); i++) {
2770+
switch (i) {
2771+
case mi_heap_tag_default: fputs("Default heap:\n", out); break;
2772+
case mi_heap_tag_obj: fputs("Object heap:\n", out); break;
2773+
}
2774+
fprintf(out, " Allocated Blocks: %ld\n", stats[i].allocated_blocks);
2775+
fprintf(out, " Allocated Bytes: %ld\n", stats[i].allocated_bytes);
2776+
fprintf(out, " Allocated Bytes w/ Overhead: %ld\n", stats[i].allocated_with_overhead);
2777+
fprintf(out, " Bytes Reserved: %ld\n", stats[i].bytes_reserved);
2778+
fprintf(out, " Bytes Committed: %ld\n", stats[i].bytes_committed);
2779+
}
2780+
2781+
return 1;
2782+
}
2783+
#endif
2784+
27212785
if (!_PyMem_PymallocEnabled()) {
27222786
return 0;
27232787
}

0 commit comments

Comments
 (0)