Skip to content

Exposing raw heap stats for threads. #995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ option(MI_NO_PADDING "Force no use of padding even in DEBUG mode etc." OF
option(MI_INSTALL_TOPLEVEL "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version" OFF)
option(MI_NO_THP "Disable transparent huge pages support on Linux/Android for the mimalloc process only" OFF)
option(MI_EXTRA_CPPDEFS "Extra pre-processor definitions (use as `-DMI_EXTRA_CPPDEFS=\"opt1=val1;opt2=val2\"`)" "")
option(MI_STAT_LEVEL "Optionally override stats level to 1 or 2 when debug not enable" 0)

# negated options for vcpkg features
option(MI_NO_USE_CXX "Use plain C compilation (has priority over MI_USE_CXX)" OFF)
Expand Down Expand Up @@ -78,6 +79,10 @@ else()
set(mi_defines "")
endif()

if (MI_STAT_LEVEL GREATER 0)
add_compile_definitions(MI_STAT=${MI_STAT_LEVEL})
endif ()

# pass git revision as a define
if(EXISTS "${CMAKE_SOURCE_DIR}/.git/index")
find_package(Git)
Expand Down
20 changes: 20 additions & 0 deletions include/mimalloc-stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,33 @@ typedef struct mi_stats_s
#undef MI_STAT_COUNT
#undef MI_STAT_COUNTER

typedef struct mi_os_stats_s {
mi_stat_count_t reserved;
mi_stat_count_t committed;
mi_stat_count_t reset;
mi_stat_count_t purged;
mi_stat_counter_t mmap_calls;
mi_stat_counter_t commit_calls;
mi_stat_counter_t reset_calls;
mi_stat_counter_t purge_calls;
} mi_os_stats_t;

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

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

// returns the thread local stats for the current thread local heap. Memory returned is non-owned.
mi_decl_export const mi_stats_t* mi_thread_stats(void) mi_attr_noexcept;

// returns the thread local stats for the given heap. Memory returned is non-owned.
mi_decl_export const mi_stats_t* mi_thread_heap_stats(const mi_heap_t* heap) mi_attr_noexcept;

// returns stats related to os memory subsystem.
mi_decl_export mi_os_stats_t mi_os_stats(void) mi_attr_noexcept;

#ifdef __cplusplus
}
Expand Down
40 changes: 40 additions & 0 deletions src/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,22 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
}
}

static void mi_stat_atomic_copy(mi_stat_count_t* dst, const mi_stat_count_t* src) {
if (dst==src) return;
if (src->total==0) return;

dst->total = (mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&src->total)));
dst->current = (mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&src->current)));
dst->peak = (mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&src->peak)));
}

static void mi_stat_counter_atomic_copy(mi_stat_counter_t* dst, const mi_stat_counter_t* src) {
if (dst==src) return;
if (src->total==0) return;

dst->total = (mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&src->total)));
}

#undef MI_STAT_COUNT
#undef MI_STAT_COUNTER

Expand Down Expand Up @@ -411,6 +427,30 @@ void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept {
_mi_stats_print(mi_stats_get_default(), out, arg);
}

const mi_stats_t* mi_thread_heap_stats(const mi_heap_t* heap) mi_attr_noexcept {
return &heap->tld->stats;
}

const mi_stats_t* mi_thread_stats(void) mi_attr_noexcept {
return mi_thread_heap_stats(mi_heap_get_default());
}

mi_os_stats_t mi_os_stats(void) mi_attr_noexcept {
mi_os_stats_t stats;
memset(&stats, 0, sizeof(mi_os_stats_t));

mi_stat_atomic_copy(&stats.reserved, &_mi_stats_main.reserved);
mi_stat_atomic_copy(&stats.committed, &_mi_stats_main.committed);
mi_stat_atomic_copy(&stats.reset, &_mi_stats_main.reset);
mi_stat_atomic_copy(&stats.purged, &_mi_stats_main.purged);

mi_stat_counter_atomic_copy(&stats.mmap_calls, &_mi_stats_main.mmap_calls);
mi_stat_counter_atomic_copy(&stats.commit_calls, &_mi_stats_main.commit_calls);
mi_stat_counter_atomic_copy(&stats.reset_calls, &_mi_stats_main.reset_calls);
mi_stat_counter_atomic_copy(&stats.purge_calls, &_mi_stats_main.purge_calls);

return stats;
}

// ----------------------------------------------------------------
// Basic timer for convenience; use milli-seconds to avoid doubles
Expand Down