Skip to content

Use bulk libunwind section registration when available - #14304

Open
macovedj wants to merge 1 commit into
bytecodealliance:mainfrom
macovedj:bulk-libunwind-compat
Open

Use bulk libunwind section registration when available#14304
macovedj wants to merge 1 commit into
bytecodealliance:mainfrom
macovedj:bulk-libunwind-compat

Conversation

@macovedj

@macovedj macovedj commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

I encountered performance issues when working with large Wasm modules similar to those described in issue #6541. That issue led to a configuration fix making it possible to opt out of native unwinding on macOS.

However, libunwind provides whole-section APIs that Wasmtime currently doesn’t use: __unw_add_dynamic_eh_frame_section and __unw_remove_dynamic_eh_frame_section. These allow registering full .eh_frame sections rather than registering each frame description entry (FDE) individually.

Testing against my large Wasm module, I measured the following median total process wall times, including teardown. Most of the improvement comes from teardown after the workload finishes.

Host / unwinder Backend Metadata: before → after Object: before → after
ARM64 macOS, Apple libunwind Cranelift 2.941 s → 1.000 s 5.248 s → 3.340 s
ARM64 macOS, Apple libunwind Winch 2.011 s → 1.923 s 6.788 s → 6.590 s
x86-64 Linux, LLVM libunwind Cranelift 4.015 s → 1.266 s 7.207 s → 4.470 s
x86-64 Linux, LLVM libunwind Winch 4.569 s → 1.842 s 9.034 s → 6.296 s

For the x86-64 Linux measurements, I explicitly selected LLVM libunwind instead of the machine’s default libgcc. LLVM libunwind is also used by configurations such as Rust’s default static musl builds, Chimera Linux, and Gentoo’s LLVM profiles. The existing libgcc registration path is unchanged.

This PR checks whether both batch registration APIs are available and uses them when they are, falling back to the existing APIs otherwise.

The native_unwind_walks_nested_wasm_frames test currently runs on x86-64 macOS and Linux. Developing it exposed an existing native stack-walking bug on ARM64 macOS, addressed in #14303. Once that fix lands, I can enable the test on ARM64 macOS as well.

@macovedj
macovedj requested a review from a team as a code owner September 9, 2026 12:54
@macovedj
macovedj requested review from pchickey and removed request for a team September 9, 2026 12:54
Register and deregister whole .eh_frame sections with libunwind when both
section APIs are available. Remember the registration mode for matching
cleanup, and retain individual-FDE registration as the fallback. The libgcc
path continues using its existing whole-section interface.

On macOS, resolve the optional APIs at runtime from the library supplying
the linked frame API. Verify the registration and deregistration identities
and restrict lookup to that image so custom unwinders cannot mix registries.
Cache the matched pair while allowing builds against older macOS SDKs.

Add native registry lifecycle and x86-64 stack-walking tests on macOS and
Linux, controlled API-availability and provider-mismatch tests, and a
linked-provider fixture that exercises the real macOS loader.
@macovedj
macovedj force-pushed the bulk-libunwind-compat branch from 25c4337 to 4ce868e Compare September 9, 2026 12:59
@github-actions github-actions Bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasmtime:api Related to the API of the `wasmtime` crate itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant