Skip to content

Advise MADV_HUGEPAGE independently of allow_large#1328

Open
rui314 wants to merge 1 commit into
microsoft:dev2from
rui314:thp-advise-huge
Open

Advise MADV_HUGEPAGE independently of allow_large#1328
rui314 wants to merge 1 commit into
microsoft:dev2from
rui314:thp-advise-huge

Conversation

@rui314

@rui314 rui314 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

On Linux with the default distro THP setting (madvise), memory becomes eligible for transparent huge pages only if the process calls madvise(MADV_HUGEPAGE) on it. mimalloc gates that advise on the caller's allow_large parameter, which callers derive from segment laziness and which primarily exists to gate MAP_HUGETLB. The
hugetlbfs half of that gate makes sense (hugetlb pages are physically committed at map time), but THP pages materialize on fault, so tying the two together means huge objects (the OS singleton path) and each thread's first segment are never THP-eligible even with MIMALLOC_ALLOW_THP=1, which is the default.

This PR makes the advise depend only on mi_option_allow_thp, leaving the hugetlbfs gate unchanged. dev3 effectively behaves this way already (singleton pages are committed eagerly and allow_large no longer depends on laziness), so this can be seen as aligning dev2 with dev3 semantics.

Motivating case: in the mold linker, the largest data structures (multi-gigabyte symbol and relocation arrays) allocate through the huge-object path. On a Chromium debug link, about 5.7 GiB of a 14.5 GiB heap stayed on 4 KiB pages; with this change the heap is almost fully huge-page backed, linking is about 2% faster in mold's default mode and 15% faster in its single-process mode, where process exit is user-visible and tearing down 2 MiB folios is far cheaper than millions of 4 KiB folios.

The THP advise was gated on the caller's allow_large parameter, which
callers derive from segment laziness and which primarily exists to
gate MAP_HUGETLB. hugetlbfs pages are physically committed at map
time, so keeping them away from lazily-committed segments makes
sense, but transparent huge pages materialize on fault and have no
such cost. As a result of sharing the gate, huge objects (the OS
singleton path) and each thread's first segment were never eligible
for THP under Linux's madvise THP mode even with allow_thp enabled.

With this change the advise depends only on the allow_thp option,
matching the effective behavior of the dev3 branch, where singleton
pages are committed eagerly and allow_large no longer depends on
laziness. In the mold linker, whose largest data structures allocate
through the huge-object path, this makes linking a Chromium debug
build about 2% faster (3.37s to 3.29s) on a 64-core machine, and 15%
faster (4.05s to 3.43s) when mold runs in its single-process mode,
where the process exit cost is user-visible and freeing a heap of
2 MiB folios is much cheaper than freeing millions of 4 KiB folios.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant