Skip to content

Update mimalloc to 3.3.0#26696

Open
kleisauke wants to merge 16 commits intoemscripten-core:mainfrom
kleisauke:mimalloc-update-3.3.0
Open

Update mimalloc to 3.3.0#26696
kleisauke wants to merge 16 commits intoemscripten-core:mainfrom
kleisauke:mimalloc-update-3.3.0

Conversation

@kleisauke
Copy link
Copy Markdown
Collaborator

@kleisauke kleisauke commented Apr 16, 2026

Resolves: #23090.
Supersedes: #23037.
Supersedes: #24542.


This contains mimalloc 8c532c32c3c96e5ba1f2283e032f69ead8add00f (v2.1.7) with
This contains mimalloc 0ddf397796fbefa35b3278bd4431c2913a9892eb (v3.3.0) with
Emscripten-specific changes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we tracking these emscripten-specific changes?

Was it easy enough for you to port them to the new version?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emscripten-specific changes are tracked in commit 8f4d480, which was created via:

  1. Replace system/lib/mimalloc/ with original mimalloc v2.1.7.
  2. Commit those changes.
  3. Upgrade to mimalloc v3.3.0.
  4. Revert the changes from step 2.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I wonder if its worth forking mimalloc in the emscripten-core org like we do for llvm and musl in order to keep track of these changes.

Perhaps not worth it as the changes are so small and we have the option to upstream most of them (I think?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably not worth creating a fork for these small changes. The changes to src/prim/emscripten/prim.c could likely be upstreamed, but I'm less certain about those in ‎src/alloc-override.c (although commit microsoft/mimalloc@a9b895e introduced a similar Emscripten-specific change to that file). I attempted to revert those weak decls with commit a4e07d4 but it was needed for test_wrap_malloc_mimalloc.

Commit 9e64b24 may also qualify as an Emscripten-specific change, but I'm not sure whether it should be documented (I've opened PR microsoft/mimalloc#1264 for this).

Comment thread test/test_core.py
@@ -8654,8 +8654,7 @@ def test_mallinfo(self):
@parameterized({
'': ([],),
'emmalloc': (['-sMALLOC=emmalloc'],),
# FIXME(https://github.com/emscripten-core/emscripten/issues/23090)
# 'mimalloc': (['-sMALLOC=mimalloc'],),
'mimalloc': (['-sMALLOC=mimalloc', '-sABORTING_MALLOC=0'],),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is ABORTING_MALLOC=0 needed here bit not for the other variants of this test?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was somehow necessary for wasm64_4gb.test_wrap_malloc_mimalloc. mimalloc was likely over-allocating internally, and this change prevented an abort().

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth a TODO to investigate?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO comment with dcf3cfd.

Comment thread tools/system_libs.py
# https://github.com/emscripten-core/emscripten/issues/20645#issuecomment-1962964755
'-DMI_ARENA_SLICE_SHIFT=(12 + MI_SIZE_SHIFT)',
# `malloc`ed pointers must be aligned at least as strictly as max_align_t
'-DMI_MAX_ALIGN_SIZE=8',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this somehow not the default?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not the default. See:

// Minimal alignment necessary. On most platforms 16 bytes are needed
// due to SSE registers for example. This must be at least `sizeof(void*)`
#ifndef MI_MAX_ALIGN_SIZE
#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t)
#endif

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I synced this with:

// Configuration: specifies the minimum alignment that malloc()ed memory outputs. Allocation requests with smaller alignment
// than this will yield an allocation with this much alignment.
#define MALLOC_ALIGNMENT alignof(max_align_t)
static_assert(alignof(max_align_t) == 8, "max_align_t must be correct");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we patch emscripten/system/lib/mimalloc/include/mimalloc/types.h to use alignof(max_align_t) directly maybe? Do you know why it doesn't already? Maybe because its C11?

But we could use the __alignof GCC/clang builtin when available?

How about:

#ifndef MI_MAX_ALIGN_SIZE 
#ifdef __GNUC__
#define MI_MAX_ALIGN_SIZE __alignof__(max_align_t)
#else
#define MI_MAX_ALIGN_SIZE  16   // sizeof(max_align_t) 
#endif
#endif 

?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MI_MAX_ALIGN_SIZE is also used in pre-processor checks, which prevents the use of function-like macros (such as _Alignof(), __alignof__() or alignof()), see:

#if (MI_MAX_ALIGN_SIZE > 4*MI_INTPTR_SIZE)
#error "define alignment for more than 4x word size for this platform"
#elif (MI_MAX_ALIGN_SIZE > 2*MI_INTPTR_SIZE)
#define MI_ALIGN4W // 4 machine words minimal alignment
#elif (MI_MAX_ALIGN_SIZE > MI_INTPTR_SIZE)
#define MI_ALIGN2W // 2 machine words minimal alignment
#else
// ok, default alignment is 1 word
#endif

Comment thread tools/system_libs.py
'-DMI_MAX_ALIGN_SIZE=8',
# reserve memory in 64 MiB chunks (internally divided by 4)
# Note: keep in sync with the -sINITIAL_HEAP default
'-DMI_DEFAULT_ARENA_RESERVE=65536',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this number if kb ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in KiB.

{ MI_DEFAULT_ARENA_RESERVE, MI_OPTION_UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`)

mi_option_arena_reserve, // initial memory size for arena reservation (= 1 GiB on 64-bit) (internally, this value is in KiB; use `mi_option_get_size`)

The / 4 happens here:

if (!_mi_os_has_virtual_reserve()) {
arena_reserve = arena_reserve/4; // be conservative if virtual reserve is not supported (for WASM for example)
}

Comment thread tools/system_libs.py
# build mimalloc with an override of malloc/free
'-DMI_MALLOC_OVERRIDE',
# TODO: add build modes that include debug checks 1,2,3
'-DMI_DEBUG=0',
# disable `assert()` in the underlying emmalloc allocator
'-DNDEBUG',
# avoid use of `__builtin_thread_pointer()`
'-DMI_LIBC_MUSL',
# enable use of `__builtin_thread_pointer()`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change from avoid => enable? Is it somehow OK to use now?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be enabled after commit llvm/llvm-project@ea58410.

Comment thread tools/system_libs.py
# build mimalloc with an override of malloc/free
'-DMI_MALLOC_OVERRIDE',
# TODO: add build modes that include debug checks 1,2,3
'-DMI_DEBUG=0',
# disable `assert()` in the underlying emmalloc allocator
'-DNDEBUG',
# avoid use of `__builtin_thread_pointer()`
'-DMI_LIBC_MUSL',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using musl so wouldn't we want to continue to define this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MI_LIBC_MUSL definition is only used by:

// Do we have __builtin_thread_pointer? This would be the preferred way to get a unique thread id
// but unfortunately, it seems we cannot test for this reliably at this time (see issue #883)
// Nevertheless, it seems needed on older graviton platforms (see issue #851).
// For now, we only enable this for specific platforms.
#if !defined(__APPLE__) /* on apple (M1) the wrong register is read (tpidr_el0 instead of tpidrro_el0) so fall back to TLS slot assembly (<https://github.com/microsoft/mimalloc/issues/343#issuecomment-763272369>)*/ \
&& !defined(__CYGWIN__) \
&& !defined(MI_LIBC_MUSL) \
&& (!defined(__clang_major__) || __clang_major__ >= 14) /* older clang versions emit bad code; fall back to using the TLS slot (<https://lore.kernel.org/linux-arm-kernel/202110280952.352F66D8@keescook/T/>) */
#if (defined(__GNUC__) && (__GNUC__ >= 7) && defined(__aarch64__)) /* aarch64 for older gcc versions (issue #851) */ \
|| (defined(__GNUC__) && (__GNUC__ >= 11) && defined(__x86_64__)) \
|| (defined(__clang_major__) && (__clang_major__ >= 14) && (defined(__aarch64__) || defined(__x86_64__)))
#define MI_USE_BUILTIN_THREAD_POINTER 1
#endif
#endif

Looking at commit microsoft/mimalloc@e46c114 and the linked issue, I don't think it applies to Emscripten.

@sbc100
Copy link
Copy Markdown
Collaborator

sbc100 commented Apr 16, 2026

Thanks for working on this!

Lgtm but let's wait for @kripken to chime in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_wrap_malloc currently failed under mimalloc

2 participants