12
12
#include <stdbool.h>
13
13
#ifdef WITH_MIMALLOC
14
14
#include "mimalloc.h"
15
+ #include "mimalloc/internal.h" // for stats
15
16
#endif
16
17
17
18
#undef uint
@@ -2708,6 +2709,29 @@ pool_is_in_list(const poolp target, poolp list)
2708
2709
}
2709
2710
#endif
2710
2711
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
+
2711
2735
/* Print summary info to "out" about the state of pymalloc's structures.
2712
2736
* In Py_DEBUG mode, also perform some expensive internal consistency
2713
2737
* checks.
@@ -2718,6 +2742,46 @@ pool_is_in_list(const poolp target, poolp list)
2718
2742
int
2719
2743
_PyObject_DebugMallocStats (FILE * out )
2720
2744
{
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
+
2721
2785
if (!_PyMem_PymallocEnabled ()) {
2722
2786
return 0 ;
2723
2787
}
0 commit comments