Repository navigation
Conversation
…ly for its own large pages mi_on_thread_idle_pending is also true when the sweep left the free blocks of an abandoned large page of the thread's heaps. Such a page is one that became full, which is where the buffers of the threads that run are, and every thread that sweeps passes all of them. A caller that is one of many helper threads (the compiler and collector threads of a runtime) and calls mi_on_thread_idle again while that is true ends an epoch per interval. A thread that takes its buffers again every few intervals then finds them given back each time. mi_on_thread_idle_pending_own is true only when one of the pages that the sweep left is a page of the thread itself. What a sweep takes does not change, and mi_on_thread_idle_pending does not change.
Collaborator
Author
|
The caller is oven-sh/WebKit#911: |
Collaborator
Author
|
One job is red: What I checked:
Can someone with access re-run the job, or paste the name of the failing test? |
…fers of a thread that runs A case with a thread that takes its large buffers again every round and a helper thread that goes idle after each round, with mi_on_thread_idle_pending as the control: following up on the any-page answer discards the buffers in every round, following up on the own-pages answer discards none. floor-free-page checks the own-pages answer for a young large page with no block in use, which is the store a thread whose blocks were all freed comes back for. mimalloc.h says that the _start/_end pair stays on the any-page answer.
Collaborator
Author
|
The job that was red passes on the new head ( The new commit adds tests and one paragraph in
oven-sh/bun#47042 moves bun's pin to this branch alone. Nothing calls the export until oven-sh/WebKit#911. |
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.
The caller is oven-sh/WebKit#911. oven-sh/bun#47042 moves bun's pin to this change first. Nothing calls the export until then.
Problem
mi_on_thread_idle_pending()is also true for an abandoned large page (src/page.c:1362). The buffers of the threads that run are in those pages, and every sweep passes them.Fix
mi_on_thread_idle_pending_own(): true when one page that the last sweep left is a page of the calling thread.mi_tld_t, set and cleared whereholes_sweep_deferredis.mi_on_thread_idle_pending()do not change.test-purge-holes-large. Each wrong answer from the new function fails a case (Notes).ctest: 41 of 41 pass.Background
mi_on_thread_idle_pending()itself. bun's Windows event loop asks it for the JS thread, which uses those abandoned pages.mi_on_thread_idle_start()/_end()pair keeps the any-page answer.mimalloc.hsays so.Downsides
.text+139 bytes (bun's flags, Linux x64). 697 of 703 code sections are byte-identical,mi_mallocandmi_freeamong them.sizeof(mi_tld_t)stays 248.Notes
Size.
.textgoes from 265,546 to 265,685 bytes.Where the flag is set.
_mi_page_purge_holes_free_page_stays(only a page of the thread comes there, frommi_theap_page_purge_holes) and_mi_page_purge_holeswhen!mi_page_is_abandoned(page). The abandoned pass (mi_arena_page_purge_holes_at) claims a page but leaves its thread id as it is, so the test holds there.Where it is cleared. With
holes_sweep_deferred:mi_on_thread_idle,_mi_theap_sweep_parked, and the fork child (subproc.c).The tests (
test/test-purge-holes-large.c).floor-free-pagenow asks the new function for a young large page with no block in use. That is the store a thread comes back for when all of its blocks were freed. The large floor has to be on for it, andmain()turns the floor off for the other cases.mimalloc.hon a helper thread, beside a thread that takes its large buffers again every round. Withmi_on_thread_idle_pending()as the key (the control) the helper discards the buffers in every round. With the new function it discards none.page.c:1243)floor-free-pageabandoned-young, and the helper caserecent-allocation,floor-free-pageWhat keeps the any-page answer.
_mi_theap_sweep_parked(the sweeps that the scavenger makes for a thread parked withmi_on_thread_idle_start()) and bun's Windows event loop. Both are for threads that run, whose buffers the abandoned pages hold.The sections that differ (clang 23,
-O3 -march=nehalem,src/static.cas bun compiles it):_mi_page_purge_holes_free_page_stays+2 bytes,_mi_page_purge_holes+30,_mi_thread_idle_work+32,mi_on_thread_idle+2,_mi_theap_sweep_parked+2,_mi_process_fork_child+0, and the new function.The measurement in bun. Each round takes 40 buffers of 256 KiB, fills them, frees them with
transfer(0), runs a collection, and computes for 300 ms without a large allocation. Minor faults of the JS thread while it fills the buffers, median of 8 rounds, 3 runs each, release build, Linux x64:mi_on_thread_idle_pending()mi_on_thread_idle_pending_own()With the third rule one round in 14 still takes about 1600 faults: the round after the JIT compiles the loop. A JIT thread then has large pages of its own, comes back for them, and its sweeps end epochs for every page.
CI.
Test (extra, macos-latest, c)failed once on the first commit (stepDebug, macOS, TLS fixed, ctest exit code 8) and passes on the current head with the other 22 checks. I could not read the log of the failed job. The same configuration passes on Linux x64.