You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Tsavorite] Scalable origin-return buffer pool + direct-VM native allocator
This change introduces two independent performance features to Tsavorite/Garnet
for reducing GC pressure and improving buffer-pool scalability under many
concurrent IO-completion threads. Both are opt-in/rollback-guarded and default
to safe behavior.
1) Scalable origin-return SectorAlignedBufferPool (new default managed backend)
- Replaces the single per-level ConcurrentQueue pool (which collapses under
concurrent cross-thread Get/Return) with a per-thread magazine pool that
routes each buffer back to its originating thread instead of the freeing
(IO-completion) thread. This avoids the memory bloat / zero-reuse asymmetry
where completion threads accumulate every buffer while issuing threads keep
allocating fresh.
- Ownership keyed by (pool, thread, size-class) via a [ThreadStatic]
recyclable-slot scheme (no ThreadLocal<T>, no monotonic-index leak).
- Seal-aware retirement/teardown protocol for dead threads and pool close,
per-buffer exactly-once permit release with a standalone BudgetState +
finalizer reclamation, a hard per-pool byte budget (anti-bloat), a
constrained linear-then-geometric size-class ladder with O(1) lookup, and
per-pool immutable mode + frozen UnpinOnReturn.
- Kill-switch: --use-legacy-buffer-pool (UseLegacyBufferPool) restores the
legacy ConcurrentQueue pool. Selected once per pool at construction via
SectorAlignedBufferPool.UseOriginReturn.
- Measured (Release, 160-core): origin-return scales 22 -> 1260 Mops/s
(1 -> 64 threads) vs legacy 44 -> 1.0 (collapses); 8M ops -> 528
allocations (8.2x working set); cross-thread p99 <= 2us.
2) Direct-VM native allocator (off | full)
- Routes large memory regions (log pages / hash index / recovery frames) off
the managed GC heap through direct OS virtual memory (mmap/VirtualAlloc).
No native library is required.
- New --native-allocator switch (NativeAllocator), NativeAllocatorSurfaces
flags, NativeAllocatorInitializer/EnvironmentInitializer, DirectVirtualMemory,
NativeMemoryTracker, and NativePageBlockRegistry.
- New INFO field native_allocator_bytes surfaces off-heap committed bytes.
- GC-sizing guidance documented in website/docs/getting-started/memory.md.
Tests: SectorAlignedBufferPoolTests (CI correctness), NativeAllocator*Tests
(hlog/recovery/server), config parsing tests for both switches, direct-VM
Docker validation, plus [Explicit] scaling/reuse/latency/soak stress harnesses.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d0cba12e-76fa-44b7-8d5c-4c9d86c5c7b1
--body "Automated refresh of the checked-in native prebuilts under \`$base\`, produced by the **Build Native Device** workflow (run ${{ github.run_id }})."
283
-
fi
284
-
;;
285
-
*)
286
-
# Feature / PR branch: commit the refreshed binaries straight onto it so the open
287
-
# PR updates in place. Re-sync with the remote tip first in case the branch moved
288
-
# during the (multi-minute) build, then push. Only the runtimes/ files change here,
289
-
# and this workflow triggers on cc/** — so this push cannot re-trigger native-build.
Copy file name to clipboardExpand all lines: libs/host/Configuration/Options.cs
+45Lines changed: 45 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -87,6 +87,14 @@ internal sealed class Options : ICloneable
87
87
[Option("index-max-size",Required=false,HelpText="Max size of hash index in bytes (rounds down to power of 2)")]
88
88
publicstringIndexMaxMemorySize{get;set;}
89
89
90
+
[Option("native-allocator",Required=false,HelpText="Route large memory regions through a native (off-managed-heap) direct-VM allocator (mmap/VirtualAlloc). Values: off (default, fully managed), full (routes log pages / hash index / recovery frames off the GC heap). No native library is required. When enabled, this memory is outside the managed GC heap: size GCHeapHardLimit to leave headroom and monitor 'native_allocator_bytes' in INFO memory.")]
91
+
[NativeAllocatorModeValidation(false)]
92
+
publicstringNativeAllocator{get;set;}
93
+
94
+
[OptionValidation]
95
+
[Option("use-legacy-buffer-pool",Required=false,HelpText="Select the per-level ConcurrentQueue SectorAlignedBufferPool instead of the default origin-return (per-thread magazine) pool. The origin-return pool returns each buffer to the thread that allocated it, so it scales with concurrent IO-completion threads under a per-pool byte budget.")]
96
+
publicbool?UseLegacyBufferPool{get;set;}
97
+
90
98
[PercentageValidation(false)]
91
99
[Option("mutable-percent",Required=false,HelpText="Percentage of log memory that is kept mutable")]
0 commit comments