Skip to content
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
2 changes: 1 addition & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ See docs/process.md for more on how version tagging works.
of `clang`. Previously, `.dwo` files were named `<input>.dwo` and other
auxiliary files were written to the temporary directory. (#28045)
- libunwind and compiler-rt were updated to LLVM 23.1.3. (#28011, #28014)
- mimalloc was updated to 3.5.3. (#28026)
- mimalloc was updated to 3.6.0. (#28026, #28068)

6.0.13 - 10/19/26
-----------------
Expand Down
2 changes: 1 addition & 1 deletion system/lib/mimalloc/README.emscripten
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

This contains mimalloc d4881d338125e1cb7c47ba4cfb398d6f7c0c8d45 (v3.5.3) with
This contains mimalloc b18ab4eef383f655e760881b02eff8af02800879 (v3.6.0) with
Emscripten-specific changes.

Origin: https://github.com/microsoft/mimalloc
Expand Down
2 changes: 1 addition & 1 deletion system/lib/mimalloc/include/mimalloc-new-delete.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ terms of the MIT license. A copy of the license can be found in the file
// ---------------------------------------------------------------------------
#if defined(__cplusplus)
#include <new>
#include <mimalloc.h>
#include "mimalloc.h"

#if defined(_MSC_VER) && defined(_Ret_notnull_) && defined(_Post_writable_byte_size_)
// stay consistent with VCRT definitions
Expand Down
2 changes: 1 addition & 1 deletion system/lib/mimalloc/include/mimalloc-override.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ each source file in a project (but be careful when using external code to
not accidentally mix pointers from different allocators).
-----------------------------------------------------------------------------*/

#include <mimalloc.h>
#include "mimalloc.h"

// Standard C allocation
#define malloc(n) mi_malloc(n)
Expand Down
40 changes: 29 additions & 11 deletions system/lib/mimalloc/include/mimalloc-profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ terms of the MIT license. A copy of the license can be found in the file
#ifndef MIMALLOC_PROFILE_H
#define MIMALLOC_PROFILE_H

#include <mimalloc.h>
#include "mimalloc.h"
#include <stdbool.h> // bool
#include <stdint.h> // uint64_t

Expand All @@ -23,29 +23,33 @@ 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`)
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);
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, 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);
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, 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);
typedef void (mi_cdecl mi_profiler_on_free_fun)(mi_profiler_t* profiler, mi_profiler_sample_data_t* profiler_data, void* ptr, mi_heap_t* heap);

// Profiling callback invoked on mi_profiler_snapshot()
typedef void (mi_cdecl mi_profiler_on_snapshot_fun)(mi_profiler_t* profiler);

// 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)
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)
mi_profiler_on_snapshot_fun* on_snapshot; // called on mi_profiler_snapshot() (only one thread at a time)
// ... more user fields allowed
};

Expand All @@ -63,7 +67,7 @@ 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
// attach a profiler to any heaps in the main sub-process (use NULL to detach)
mi_decl_export bool mi_profile(mi_profiler_t* profiler);

// start sampling
Expand All @@ -72,6 +76,20 @@ mi_decl_export bool mi_profiler_start(mi_profiler_t* profiler);
// end sampling
mi_decl_export bool mi_profiler_stop(mi_profiler_t* profiler);

// snapshot the current profile (may be called concurrently but only one thread will actually call the snapshot callback)
mi_decl_export void mi_profiler_snapshot(mi_profiler_t* profiler);

// builtin pprof compatible profiler
// the builtin profiler can also be activated using environment variables (see [`pprof.c`](/src/profile/pprof.c))
// `base_file_name` selects the text snapshot format if it ends in `.heap` or `.text` (the extension is
// stripped); any other extension, or none, uses the default (protobuf) snapshot format.
// `alloc_interval_size`, if >0, automatically snapshots every that many allocated bytes.
// `inuse_interval_size`, if >0, automatically snapshots every time the in-use bytes grow by that many bytes.
// `time_interval_secs`, if >0, automatically snapshots every that many seconds (checked from allocation events).
mi_decl_export mi_profiler_t* mi_pprof_profiler_new(size_t initial_threshold, const char* base_file_name, size_t alloc_interval_size, size_t inuse_interval_size, size_t time_interval_secs);
mi_decl_export void mi_pprof_profiler_delete(mi_profiler_t* profiler);


#ifdef __cplusplus
}
#endif
Expand Down
25 changes: 17 additions & 8 deletions system/lib/mimalloc/include/mimalloc-stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ terms of the MIT license. A copy of the license can be found in the file
#ifndef MIMALLOC_STATS_H
#define MIMALLOC_STATS_H

#include <mimalloc.h>
#include "mimalloc.h"
#include <string.h> // memset
#include <stdint.h> // int64_t

#define MI_STAT_VERSION 5 // increased on every backward incompatible change
#define MI_STAT_VERSION 6 // increased on every backward incompatible change

// alignment for atomic fields
#if defined(_MSC_VER)
Expand Down Expand Up @@ -47,17 +47,17 @@ typedef struct mi_stat_counter_s {
MI_STAT_COUNT(page_committed) /* committed memory inside pages */ \
MI_STAT_COUNT(pages_abandoned) /* abandoned 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(allocated) /* allocated bytes */ \
MI_STAT_COUNTER(malloc_count) /* total number of malloc calls */ \
MI_STAT_COUNTER(free_count) /* total number of free calls */ \
MI_STAT_COUNTER(freed) /* total free'd bytes (note: total allocated is `allocated.total`) */ \
MI_STAT_COUNTER(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 */ \
Expand All @@ -81,10 +81,17 @@ typedef struct mi_stat_counter_s {
MI_STAT_COUNTER(pages_reclaim_on_free) \
MI_STAT_COUNTER(pages_reabandon_full) \
MI_STAT_COUNTER(pages_unabandon_busy_wait) \
MI_STAT_COUNTER(pages_unown_cas_retry) \
MI_STAT_COUNTER(heaps_delete_wait) \
MI_STAT_COUNTER(pages_stat_updates) /* calls to successful page_stat_update */ \
MI_STAT_COUNTER(pages_stat_update_count) /* total free/allocs */ \
MI_STAT_COUNTER(profile_samples) /* total sampled profiled allocations */ \
/* deprecated */ \
MI_STAT_COUNT(malloc_normal) /* allocated bytes <= MI_LARGE_OBJ_SIZE_MAX */ \
MI_STAT_COUNT(malloc_huge) /* allocated bytes in huge pages */ \
MI_STAT_COUNTER(malloc_normal_count) /* number of blocks <= MI_LARGE_OBJ_SIZE_MAX */ \
MI_STAT_COUNTER(malloc_huge_count) /* number of huge bloks */ \


// Size bins for chunks
typedef enum mi_chunkbin_e {
Expand All @@ -105,8 +112,8 @@ typedef enum mi_chunkbin_e {

typedef struct mi_stats_s
{
size_t size; // size of the mi_stats_t structure
size_t version;
size_t size; // size of the mi_stats_t structure
size_t version;

mi_decl_align(8) MI_STAT_FIELDS()

Expand All @@ -133,6 +140,8 @@ static inline void mi_stats_init(mi_stats_t* stats) {
mi_stats_header_init(stats);
}

// Always use this to declare and initialize a `mi_stats_t` variable such
// that the version and size can be checked at runtime.
#define mi_stats_t_decl(name) mi_stats_t name; mi_stats_init(&name);

// Exported definitions
Expand Down
Loading
Loading