/* ---------------------------------------------------------------------------- Copyright (c) 2024-2026, 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_PROFILE_H #define MIMALLOC_PROFILE_H #include #include // bool #include // uint64_t //--------------------------------------------------------------------------- // Initial support for profiling hooks; still experimental //--------------------------------------------------------------------------- #define MI_PROFILE_SAMPLE_DATA_MAX_SIZE (1024) // User defined profiler; see `test_profile.c` for an example. typedef struct mi_profiler_s mi_profiler_t; // Profiler data is stored together with each sampled allocation (unless the `on_free` field in the profiler is NULL.) typedef struct mi_profiler_sample_data_s { size_t user_data_size; // size of the user_data (should be the `mi_profiler_t.sample_data_size`) void* user_data[1]; // default, but can be less or more (up to 1KiB), depending on `sample_data_size` } mi_profiler_sample_data_t; // Profiling callback invoked on each sampled allocation. // If `profiler_data!=NULL` (i.e. when `on_free` is not NULL), then `profiler_data->requested_size == requested_size`. typedef size_t (mi_cdecl mi_profiler_on_alloc_fun )(mi_profiler_t* profiler, mi_profiler_sample_data_t* profiler_data, void* ptr, size_t requested_size, size_t bytes_sample_rate, uint64_t bytes_since_last_sample, const mi_heap_t* heap); // Profiling callback invoked on each sampled in-place re-allocation. typedef size_t (mi_cdecl mi_profiler_on_realloc_inplace_fun)(mi_profiler_t* profiler, mi_profiler_sample_data_t* profiler_data, void* ptr, size_t old_size, const mi_heap_t* heap); // Profiling callback invoked on a previously sampled allocation. typedef void (mi_cdecl mi_profiler_on_free_fun )(mi_profiler_t* profiler, mi_profiler_sample_data_t* profiler_data, void* ptr, const mi_heap_t* heap); // A profiler // All fields are considered immutable such that they can be copied and accessed concurrently. All fields can be NULL/0. struct mi_profiler_s { void* reserved; // opaque; reserved by mimalloc size_t sample_data_size; // size of required profiler data for each sampled allocation (or zero for no data) size_t initial_sample_rate;// initial sample rate in bytes (set to at least 1 or higher) (can be adjusted by `on_alloc`) mi_profiler_on_alloc_fun* on_alloc; // called on a sampled allocation (may be called concurrently) mi_profiler_on_free_fun* on_free; // called on when previous sampled allocation is freed (may be called concurrently) mi_profiler_on_realloc_inplace_fun* on_realloc_inplace; // (as yet unused) called on in-place reallocation of a previous sampled allocation (may be called concurrently) // ... more user fields allowed }; // Exported definitions #ifdef __cplusplus extern "C" { #endif // attach a profiler to a particular heap only. mi_decl_export bool mi_heap_profile(mi_heap_t* heap, mi_profiler_t* profiler); // disable profiling for a particular heap; useful for a heap that the profiler uses itself for metadata. mi_decl_export void mi_heap_profile_disable(mi_heap_t* heap); // attach a profiler to any (current and future) heaps in a sub-process (unless those heaps disabled profiling) mi_decl_export bool mi_subproc_profile(mi_subproc_id_t subproc_id, mi_profiler_t* profiler); // attach a profiler to any heaps in the main sub-process mi_decl_export bool mi_profile(mi_profiler_t* profiler); // start sampling mi_decl_export bool mi_profiler_start(mi_profiler_t* profiler); // end sampling mi_decl_export bool mi_profiler_stop(mi_profiler_t* profiler); #ifdef __cplusplus } #endif #endif // MIMALLOC_PROFILE_H