Snapshot support for embedders - #13
Open
Jarred-Sumner wants to merge 2 commits into
Open
Conversation
Jarred-Sumner
added a commit
to oven-sh/bun
that referenced
this pull request
Aug 8, 2026
…les on this branch — the branch now builds from the download exactly like main does
Jarred-Sumner
force-pushed
the
claude/heap-image
branch
from
August 8, 2026 23:59
8ecfcde to
b9aedbc
Compare
Jarred-Sumner
added a commit
to oven-sh/bun
that referenced
this pull request
Aug 9, 2026
Jarred-Sumner
force-pushed
the
claude/heap-image
branch
2 times, most recently
from
August 9, 2026 05:20
aae392c to
7841fec
Compare
…live samples; size the location table to the sample count The thread that held the profiler lock in the parent (or in the process that built a snapshot) does not exist in the child, so the lock is re-initialized there. mi_prof_visit_live() lets an embedder walk the live sampled allocations, and mi_prof_lock_is_free() lets it assert the profiler is quiescent before freezing memory. The location table used while aggregating grows with the sample count instead of being fixed at 4096 entries.
Jarred-Sumner
force-pushed
the
claude/heap-image
branch
4 times, most recently
from
August 9, 2026 10:22
018ddb2 to
f593ef8
Compare
An embedder can freeze the current heap into a snapshot and map it into later processes. This adds what the allocator needs for that: pages captured in a snapshot get the thread id MI_THREADID_FROZEN, so frees of their blocks are dropped on the (already slow) cross-thread path and collection, purging and the idle hole sweep leave them alone; mi_theap_freeze() marks the frozen theaps; mi_arenas_seal_existing() stops new allocation from landing in frozen arenas; mi_theap_adopt_current_thread() lets the resuming thread take over the frozen main-thread state (otherwise every page it allocates carries a thread id nobody has and all of its frees go cross-thread); mi_heap_snapshot_hints_enabled() exports the deterministic-placement decision, made once, so the embedder's own reservations follow the same rule. Placement is deterministic when the host executable says it can carry a snapshot (MI_HEAP_SNAPSHOT_HOST_FN) or MIMALLOC_DETERMINISTIC_HINT is set; a capable process that is not taking a snapshot keeps its early allocations above MI_HEAP_SNAPSHOT_RESTORER_FLOOR so they never sit where the snapshot will be mapped. The hole-sweep bookkeeping moves from __thread variables onto the tld: on macOS the first touch of a thread-local from inside the allocator makes dyld allocate the TLV block with malloc, which re-enters the allocator before the variable exists. Nothing here runs in a process that neither takes nor maps a snapshot, apart from the frozen-id compare on the cross-thread free path.
Jarred-Sumner
force-pushed
the
claude/heap-image
branch
from
August 9, 2026 10:35
f593ef8 to
7aca49e
Compare
Jarred-Sumner
marked this pull request as ready for review
August 9, 2026 14:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Allocator side of Bun's heap images (an embedder freezes a process's heap into a file and maps it into fresh processes). 240 lines; everything is behind new entry points or embedder-supplied defines, and the malloc/free fast paths are unchanged. Full rationale in the second commit's message.
MI_HEAP_IMAGE_HOST_FN/MI_HEAP_IMAGE_BUILD_ENV,mi_os_hint_floor()MI_THREADID_FROZEN,mi_arenas_freeze_pages()mi_arenas_seal_existing(),mi_theap_freeze(),mi_arenas_visit_free_ranges()mi_malloc_zone_process_owned_ranges()(macOS)__threadvariables onto the swepttldprof.c:mi_prof_reinit_lock,mi_prof_visit_live,mi_prof_lock_is_freeExercised by
test/js/bun/heap-imageon the Bun side (oven-sh/bun branchclaude/lowmem-cc) and by an application that has been running from an image for a day. Companion: oven-sh/WebKit#397 (JSC side). Draft until the Bun side is up for review.