File: mimalloc-stats.h

package info (click to toggle)
mimalloc 3.2.7%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 1,336 kB
  • sloc: ansic: 16,817; cpp: 489; makefile: 21
file content (149 lines) | stat: -rw-r--r-- 6,425 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* ----------------------------------------------------------------------------
Copyright (c) 2024-2025, Microsoft Research, Daan Leijen
This is free software; you can redistribute it and/or modify it under the
terms of the MIT license. A copy of the license can be found in the file
"LICENSE" at the root of this distribution.
-----------------------------------------------------------------------------*/
#pragma once
#ifndef MIMALLOC_STATS_H
#define MIMALLOC_STATS_H

#include <mimalloc.h>
#include <stdint.h>

#define MI_STAT_VERSION   3   // increased on every backward incompatible change

// alignment for atomic fields
#if defined(_MSC_VER)
#define mi_decl_align(a)        __declspec(align(a))
#elif defined(__GNUC__)
#define mi_decl_align(a)        __attribute__((aligned(a)))
#elif __cplusplus >= 201103L
#define mi_decl_align(a)        alignas(a)
#else
#define mi_decl_align(a)
#endif


// count allocation over time
typedef struct mi_stat_count_s {
  int64_t total;                              // total allocated
  int64_t peak;                               // peak allocation
  int64_t current;                            // current allocation
} mi_stat_count_t;

// counters only increase
typedef struct mi_stat_counter_s {
  int64_t total;                              // total count
} mi_stat_counter_t;

#define MI_STAT_FIELDS() \
  MI_STAT_COUNT(pages)                      /* count of mimalloc pages */ \
  MI_STAT_COUNT(reserved)                   /* reserved memory bytes */ \
  MI_STAT_COUNT(committed)                  /* committed bytes */ \
  MI_STAT_COUNTER(reset)                    /* reset bytes */ \
  MI_STAT_COUNTER(purged)                   /* purged bytes */ \
  MI_STAT_COUNT(page_committed)             /* committed memory inside pages */ \
  MI_STAT_COUNT(pages_abandoned)            /* abandonded pages count */ \
  MI_STAT_COUNT(threads)                    /* number of threads */ \
  MI_STAT_COUNT(malloc_normal)              /* allocated bytes <= MI_LARGE_OBJ_SIZE_MAX */ \
  MI_STAT_COUNT(malloc_huge)                /* allocated bytes in huge pages */ \
  MI_STAT_COUNT(malloc_requested)           /* malloc requested bytes */ \
  \
  MI_STAT_COUNTER(mmap_calls) \
  MI_STAT_COUNTER(commit_calls) \
  MI_STAT_COUNTER(reset_calls) \
  MI_STAT_COUNTER(purge_calls) \
  MI_STAT_COUNTER(arena_count)              /* number of memory arena's */ \
  MI_STAT_COUNTER(malloc_normal_count)      /* number of blocks <= MI_LARGE_OBJ_SIZE_MAX */ \
  MI_STAT_COUNTER(malloc_huge_count)        /* number of huge bloks */ \
  MI_STAT_COUNTER(malloc_guarded_count)     /* number of allocations with guard pages */ \
  \
  /* internal statistics */ \
  MI_STAT_COUNTER(arena_rollback_count) \
  MI_STAT_COUNTER(arena_purges) \
  MI_STAT_COUNTER(pages_extended)           /* number of page extensions */ \
  MI_STAT_COUNTER(pages_retire)             /* number of pages that are retired */ \
  MI_STAT_COUNTER(page_searches)            /* total pages searched for a fresh page */ \
  MI_STAT_COUNTER(page_searches_count)      /* searched count for a fresh page */ \
  /* only on v1 and v2 */ \
  MI_STAT_COUNT(segments) \
  MI_STAT_COUNT(segments_abandoned) \
  MI_STAT_COUNT(segments_cache) \
  MI_STAT_COUNT(_segments_reserved) \
  /* only on v3 */ \
  MI_STAT_COUNT(heaps) \
  MI_STAT_COUNTER(pages_reclaim_on_alloc) \
  MI_STAT_COUNTER(pages_reclaim_on_free) \
  MI_STAT_COUNTER(pages_reabandon_full) \
  MI_STAT_COUNTER(pages_unabandon_busy_wait)

// Size bins for chunks
typedef enum mi_chunkbin_e {
  MI_CBIN_SMALL,    // slice_count == 1
  MI_CBIN_OTHER,    // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS
  MI_CBIN_MEDIUM,   // slice_count == 8
  MI_CBIN_LARGE,    // slice_count == MI_SIZE_BITS  (only used if MI_ENABLE_LARGE_PAGES is 1)
  MI_CBIN_HUGE,     // slice_count > MI_BCHUNK_BITS
  MI_CBIN_NONE,     // no bin assigned yet (the chunk is completely free)
  MI_CBIN_COUNT
} mi_chunkbin_t;


// Define the statistics structure
#define MI_BIN_HUGE             (73U)   // see types.h
#define MI_STAT_COUNT(stat)     mi_stat_count_t stat;
#define MI_STAT_COUNTER(stat)   mi_stat_counter_t stat;

typedef struct mi_stats_s
{
  int version;

  mi_decl_align(8)  MI_STAT_FIELDS()

  // future extension
  mi_stat_count_t   _stat_reserved[4];
  mi_stat_counter_t _stat_counter_reserved[4];

  // size segregated statistics
  mi_stat_count_t   malloc_bins[MI_BIN_HUGE+1];   // allocation per size bin
  mi_stat_count_t   page_bins[MI_BIN_HUGE+1];     // pages allocated per size bin
  mi_stat_count_t   chunk_bins[MI_CBIN_COUNT];    // chunks per page sizes
} mi_stats_t;

#undef MI_STAT_COUNT
#undef MI_STAT_COUNTER


// Exported definitions
#ifdef __cplusplus
extern "C" {
#endif

// stats from a heap
mi_decl_export void    mi_heap_stats_get(mi_heap_t* heap, size_t stats_size, mi_stats_t* stats) mi_attr_noexcept;
mi_decl_export char*   mi_heap_stats_get_json(mi_heap_t* heap, size_t buf_size, char* buf) mi_attr_noexcept;      // use mi_free to free the result if the input buf == NULL
mi_decl_export void    mi_heap_stats_print_out(mi_heap_t* heap, mi_output_fun* out, void* arg) mi_attr_noexcept;
mi_decl_export void    mi_heap_stats_merge_to_subproc(mi_heap_t* heap);

// subprocess stats
mi_decl_export void    mi_subproc_stats_get(mi_subproc_id_t subproc_id, size_t stats_size, mi_stats_t* stats) mi_attr_noexcept;
mi_decl_export char*   mi_subproc_stats_get_json(mi_subproc_id_t subproc_id, size_t buf_size, char* buf) mi_attr_noexcept;      // use mi_free to free the result if the input buf == NULL
mi_decl_export void    mi_subproc_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun* out, void* arg) mi_attr_noexcept;

// subprocess and its heap stats segregated
mi_decl_export void    mi_subproc_heap_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun* out, void* arg) mi_attr_noexcept;

// stats aggregated for the current subprocess and all its heaps.
mi_decl_export void    mi_stats_get(size_t stats_size, mi_stats_t* stats) mi_attr_noexcept;
mi_decl_export char*   mi_stats_get_json(size_t buf_size, char* buf) mi_attr_noexcept;      // use mi_free to free the result if the input buf == NULL
mi_decl_export void    mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;


mi_decl_export size_t  mi_stats_get_bin_size(size_t bin) mi_attr_noexcept;

#ifdef __cplusplus
}
#endif

#endif // MIMALLOC_STATS_H