Skip to content

perf: store the fulfillment engine inline in ObligationCtxt - #47

Closed
xmakro wants to merge 1 commit into
perf/base-0713from
perf/obligation-ctxt-inline-engine
Closed

perf: store the fulfillment engine inline in ObligationCtxt#47
xmakro wants to merge 1 commit into
perf/base-0713from
perf/obligation-ctxt-inline-engine

Conversation

@xmakro

@xmakro xmakro commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Every ObligationCtxt allocated its fulfillment engine on the heap as a Box<dyn TraitEngine>. This was the single largest allocation site in the compiler: 161k allocations on a syn check build (measured with DHAT). ObligationCtxts are created in hot paths, for example once per candidate probe during method resolution.

The allocation is easy to avoid. Which solver is used never changes during a compilation session, and both engine types are small (the obligation forest allocates its own storage separately). So this PR stores the engine directly inside ObligationCtxt, in a two-variant enum. Calls now go through a match on that enum instead of virtual dispatch.

The enum's TraitEngine impl needs both FromSolverError bounds, so a few generic impl blocks and two generic users now need both bounds as well. The concrete error types used in practice already implement both, so nothing else changes for callers. The typeck root fulfillment context keeps the boxed engine; it is created once per function body, so the allocation does not matter there.

@xmakro xmakro changed the title Store the fulfillment engine inline in ObligationCtxt Store the fulfillment engine inline in ObligationCtxt [in -0.46% batch] Jul 14, 2026
@xmakro xmakro changed the title Store the fulfillment engine inline in ObligationCtxt [in -0.46% batch] Store the fulfillment engine inline in ObligationCtxt [-0.18% avg] Jul 14, 2026
@xmakro xmakro changed the title Store the fulfillment engine inline in ObligationCtxt [-0.18% avg] perf: store the fulfillment engine inline in ObligationCtxt Jul 31, 2026
Every ObligationCtxt heap-allocated its fulfillment engine as a
Box<dyn TraitEngine>, making it the single largest allocation site in
the compiler (161k allocations on a syn check build, created per
candidate probe in method resolution among others). The solver choice
is a per-session constant and both engine types are small, so store
them inline in a two-variant enum with static dispatch.

The enum's TraitEngine impl needs both FromSolverError bounds, which
ripples to the generic impl blocks and two generic users; the concrete
error types used everywhere implement both. The boxed engine remains
for the per-body typeck root fulfillment context.
@xmakro
xmakro force-pushed the perf/obligation-ctxt-inline-engine branch from bcdadb6 to aa264ca Compare July 31, 2026 09:27
@xmakro xmakro closed this Jul 31, 2026
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