Skip to content

Add compile-time inline ownership hook (ALLOC8_XXOWNS_INLINE_HEADER)#9

Merged
emeryberger merged 1 commit into
mainfrom
inline-owns-hook
Jul 9, 2026
Merged

Add compile-time inline ownership hook (ALLOC8_XXOWNS_INLINE_HEADER)#9
emeryberger merged 1 commit into
mainfrom
inline-owns-hook

Conversation

@emeryberger

Copy link
Copy Markdown
Owner

Summary

Adds a third, fastest ownership-dispatch mode to the macOS wrapper: a compile-time inline hook. The consumer defines ALLOC8_XXOWNS_INLINE_HEADER (directly or via the new CMake cache variable) naming a header that provides:

static inline bool alloc8_xxowns_inline(const void* p);

with the same contract as xxowns() — safe on any address, no false positives or negatives.

Why

The runtime xxowns() hook always costs one function call per free/realloc/malloc_size: the weak module-local default definition blocks cross-module inlining under (Thin)LTO, so even a two-load ownership predicate pays call overhead on every operation. Profiling Hoard on larson showed the wrapper layer (entry checks + the xxowns call) at ~25–30% of total cycles.

Because the interpose sources are compiled inside the consumer's target, a compile-time hook inlines straight into replace_free / replace_realloc / replace_malloc_size; the runtime "do we have a hook?" branch disappears and per-allocation track/untrack bookkeeping compiles away entirely. After this change, replace_free's owned-pointer path contains zero calls.

Results (Hoard on M1 Max, 8 threads, runtime hook → inline hook)

benchmark before after
larson (ops/s) 185M 211M (+14%)
threadtest (s) 0.85 0.66 (−23%)
linux-scalability (s) 0.127 0.093 (−27%)

Compatibility

  • Allocators that don't opt in are completely unaffected (runtime xxowns() and the internal size table are unchanged).
  • Consumers may set the define even when building against older alloc8: it is simply ignored.
  • Companion Hoard PR: emeryberger/Hoard (ownership-map + size-class optimization series) opts in via hoardownsinline.h.

Testing

  • Built into Hoard on macOS arm64; verified via disassembly that the predicate fully inlines (no bl on the owned-free path).
  • Multi-threaded stress test (pattern-verified malloc/free/realloc/calloc/posix_memalign with cross-thread frees) passes.
  • Full benchmark suite (threadtest, larson, linux-scalability, cache-scratch/thrash) runs correctly.

🤖 Generated with Claude Code

The runtime xxowns() hook always costs one function call per
free/realloc/malloc_size: the weak module-local default definition
blocks cross-module inlining under (Thin)LTO, so even an allocator
that provides a two-load ownership predicate pays call overhead on
every operation. Profiling Hoard on larson showed the wrapper layer
(entry checks + the xxowns call) at roughly 25-30% of total cycles.

Since the macOS interpose sources are compiled inside the consumer's
target, a compile-time hook can do better: the consumer defines
ALLOC8_XXOWNS_INLINE_HEADER (directly or via the new CMake cache
variable) naming a header that provides

    static inline bool alloc8_xxowns_inline(const void* p);

with the same contract as xxowns() (safe on any address, no false
positives or negatives). The predicate then inlines straight into
replace_free / replace_realloc / replace_malloc_size, the runtime
"do we have a hook?" branch disappears, and per-allocation
track/untrack bookkeeping compiles away entirely.

Measured with Hoard on an M1 Max (8 threads), runtime hook -> inline
hook: larson 185M -> 211M ops/s (+14%), threadtest 0.85s -> 0.66s
(-23%), linux-scalability 0.127s -> 0.093s (-27%).

The runtime xxowns() path and the internal size table are unchanged
for allocators that do not opt in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@emeryberger emeryberger merged commit 7cc63f6 into main Jul 9, 2026
8 checks passed
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