Skip to content

[alloc+set] Introducing next-generation bstack SegregatedBStackAllocator - #40

Merged
williamwutq merged 14 commits into
masterfrom
alloc
Aug 13, 2026
Merged

[alloc+set] Introducing next-generation bstack SegregatedBStackAllocator#40
williamwutq merged 14 commits into
masterfrom
alloc

Conversation

@williamwutq

@williamwutq williamwutq commented Aug 13, 2026

Copy link
Copy Markdown
Owner

SegregatedBStackAllocator

Description: Segregated (binned) free-list allocator for [BStack]-backed storage, which generalises the fixed-block slab (CheckedSlabBStackAllocator) to NUM_CLASSES size classes sharing one arena. Each class is an independent intrusive free list; alloc computes the class from the request with register arithmetic and pops a single fixed-shape head, falling back to a tail extension on a miss (the slab pop, else extend rule). Requests above the largest class collapse onto one shared oversized list. It is intended to achieves next-generation performance by reducing io calls while ensure crash-safety and recoverability for orphaned blocks.

Caveat:
Background coalescer is not implemented. Recovery currently requires exclusive access and cannot be run concurrently. This is fine for this PR since it introduces this as experimental.

Important Feature: No
Type: Allocator
Magic Number: ALSG
Bulk: No
Tests: Needed
Feature Flags: alloc + set (+ atomic)
Breaking change: No
New Types: SegregatedBStackAllocator
Rust Only: Yes for this PR
Fuzz: Yes
Safety Review: Needed: Crash Safety, Invariants

@williamwutq williamwutq self-assigned this Aug 13, 2026
@williamwutq

Copy link
Copy Markdown
Owner Author

Quintiles — per-iteration time (ms), n = 100

uniform

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 5.48 6.60 6.60 6.61 6.80 7.00 7.99 0.40
ghost_tree 1t 2.25 2.99 3.00 3.00 3.00 3.02 4.03 0.02
segregated 1t 3.20 3.68 4.14 4.37 4.42 4.62 7.24 0.79
first_fit 2t 5.67 6.60 6.60 6.61 6.79 9.79 12.61 1.03
ghost_tree 2t 2.83 2.99 3.00 3.00 3.00 3.02 4.00 0.02
segregated 2t 4.04 4.51 4.80 4.90 4.98 5.18 7.01 0.53
first_fit 4t 2.00 2.99 3.00 3.01 3.30 3.33 3.99 0.34
ghost_tree 4t 2.82 2.98 2.99 3.00 3.00 3.01 5.00 0.02
segregated 4t 1.18 2.24 3.97 4.00 4.32 4.67 5.62 2.28
first_fit 16t 2.57 2.93 2.96 2.97 2.99 3.27 3.90 0.32
ghost_tree 16t 5.54 5.99 6.00 6.00 6.05 6.19 7.97 0.19
segregated 16t 3.77 3.94 4.30 4.34 4.38 4.85 6.73 0.64

gamma-k2-t0.25

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 3.93 3.99 4.01 4.02 4.05 4.97 10.31 0.57
ghost_tree 1t 5.19 5.79 5.99 6.00 6.01 6.21 7.93 0.39
segregated 1t 3.20 3.78 4.01 4.06 4.20 4.42 5.43 0.54
first_fit 2t 3.85 3.99 4.01 4.04 4.18 4.55 14.18 0.52
ghost_tree 2t 2.33 2.79 2.99 3.00 3.01 3.12 4.01 0.09
segregated 2t 3.00 3.61 3.90 3.99 4.02 4.15 5.54 0.40
first_fit 4t 3.90 3.99 4.07 4.22 4.46 5.01 7.77 0.83
ghost_tree 4t 2.49 2.98 2.99 3.00 3.00 3.33 4.00 0.26
segregated 4t 3.14 3.95 4.26 4.40 4.73 5.86 7.26 1.49
first_fit 16t 2.19 2.92 2.95 2.97 2.99 3.20 4.16 0.21
ghost_tree 16t 3.93 5.76 5.80 5.94 5.98 6.09 25.75 0.21
segregated 16t 1.19 1.90 2.19 2.28 2.34 2.46 3.92 0.46

bimodal-s32-p0.2

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 1.66 2.99 3.22 3.32 3.33 3.34 4.84 0.33
ghost_tree 1t 3.85 3.98 4.00 4.01 4.10 4.50 11.00 0.48
segregated 1t 3.89 3.98 4.00 4.02 4.11 4.49 7.41 0.44
first_fit 2t 5.80 6.40 8.80 9.00 9.19 9.98 41.56 3.20
ghost_tree 2t 3.74 3.98 4.00 4.01 4.03 4.45 6.70 0.30
segregated 2t 3.85 3.98 4.00 4.01 4.06 4.51 12.15 0.46
first_fit 4t 3.88 3.97 3.99 4.03 4.08 4.42 10.14 0.33
ghost_tree 4t 5.48 7.29 7.35 7.54 7.67 8.13 14.57 0.67
segregated 4t 3.93 3.98 4.01 4.05 4.18 4.51 8.85 0.49
first_fit 16t 3.75 3.91 3.98 4.24 4.31 4.42 6.44 0.45
ghost_tree 16t 3.69 3.94 3.99 4.01 4.25 4.46 6.02 0.49
segregated 16t 3.77 6.60 6.96 7.01 7.14 7.35 8.95 0.57

Median (p50) summary + segregated speedup

vs_ff = first_fit / segregated, vs_gt = ghost_tree / segregated. > 1.00× = segregated faster.

workload thr first_fit ghost_tree segregated vs_ff vs_gt
uniform 1 6.611 2.997 4.367 1.51× 0.69×
uniform 2 6.606 3.000 4.896 1.35× 0.61×
uniform 4 3.007 2.995 4.001 0.75× 0.75×
uniform 16 2.970 6.003 4.343 0.68× 1.38×
gamma-k2-t0.25 1 4.019 5.999 4.064 0.99× 1.48×
gamma-k2-t0.25 2 4.037 2.998 3.993 1.01× 0.75×
gamma-k2-t0.25 4 4.216 2.995 4.404 0.96× 0.68×
gamma-k2-t0.25 16 2.966 5.938 2.281 1.30× 2.60×
bimodal-s32-p0.2 1 3.316 4.008 4.022 0.82× 1.00×
bimodal-s32-p0.2 2 8.997 4.014 4.011 2.24× 1.00×
bimodal-s32-p0.2 4 4.028 7.541 4.047 1.00× 1.86×
bimodal-s32-p0.2 16 4.240 4.009 7.005 0.61× 0.57×

@williamwutq

Copy link
Copy Markdown
Owner Author

Segregated allocator throughput benchmark

cargo bench --bench alloc --features "alloc set atomic" (release), comparing
SegregatedBStackAllocator against FirstFitBStackAllocator and GhostTreeBstackAllocator
over three size distributions (uniform, gamma:k=2:θ=0.25, bimodal:small=32:p_large=0.2)
under the mixed op mix, on one shared allocator at 1/2/4/16 threads. Config:
BSTACK_BENCH_PRE_ALLOC=64, --sample-size 100 --measurement-time 60 --warm-up-time 3; the
metric is per-iteration wall time (ms), reported as quintiles over 100 samples. Run 2026-08-13,
Apple M2 Pro (10 core / 16 GB).

Load average held at 1.08–3.32 (median 1.72) and each op is a durable fsync, so the workload is
disk-bound rather than CPU-bound and background noise is negligible — no cell is flagged.
Absolute times therefore measure fsync-per-op throughput at a churn-heavy pre_alloc=64
operating point; the relative ordering is the robust result.

Quintiles — per-iteration time (ms), n = 100

uniform

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 12.83 13.22 13.29 13.31 13.32 13.38 13.63 0.13
ghost_tree 1t 21.04 21.99 22.12 22.15 22.21 22.29 22.76 0.22
segregated 1t 1.41 7.37 8.58 11.44 12.42 13.64 18.61 5.60
first_fit 2t 10.08 11.12 11.36 11.60 12.14 12.72 15.33 1.26
ghost_tree 2t 9.96 10.60 10.72 10.77 10.89 11.28 17.72 0.61
segregated 2t 1.40 6.89 7.74 8.34 9.41 10.40 20.47 3.03
first_fit 4t 10.27 12.78 13.80 14.04 14.73 15.61 18.18 2.14
ghost_tree 4t 10.31 11.90 12.57 13.11 13.42 14.76 24.90 2.05
segregated 4t 1.45 6.60 7.47 8.21 9.10 9.94 10.96 2.69
first_fit 16t 12.96 14.83 15.60 15.77 16.16 16.94 18.50 1.68
ghost_tree 16t 24.90 25.15 25.22 25.26 25.38 25.78 31.69 0.46
segregated 16t 1.13 6.70 7.52 7.85 8.45 9.65 10.87 2.49

gamma-k2-t0.25

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 2.24 12.45 14.98 15.82 16.66 18.59 20.56 4.59
ghost_tree 1t 12.94 13.78 13.83 13.89 13.89 13.95 14.50 0.13
segregated 1t 1.34 6.49 7.43 7.99 8.48 9.39 10.59 2.40
first_fit 2t 9.65 10.21 10.50 10.54 10.58 10.72 11.34 0.36
ghost_tree 2t 8.05 9.90 10.00 10.10 10.35 13.25 13.85 3.00
segregated 2t 1.43 6.47 7.38 8.25 8.75 9.93 11.13 2.75
first_fit 4t 8.96 9.88 10.66 10.82 10.99 11.63 14.00 1.48
ghost_tree 4t 9.01 11.25 11.84 12.08 12.84 13.69 17.35 2.05
segregated 4t 1.88 6.39 7.82 8.36 8.84 9.80 11.02 2.65
first_fit 16t 8.41 10.02 10.54 10.68 10.83 11.32 11.95 0.93
ghost_tree 16t 7.95 10.14 10.76 11.07 11.60 12.65 15.91 1.91
segregated 16t 1.03 6.32 7.29 7.68 8.23 9.63 11.03 2.85

bimodal-s32-p0.2

alloc / thr min p20 p40 p50 p60 p80 max IQR
first_fit 1t 2.88 10.91 12.85 13.29 14.14 15.84 19.23 3.90
ghost_tree 1t 17.19 17.35 17.40 17.45 17.47 17.97 20.00 0.32
segregated 1t 1.35 6.02 6.79 7.19 7.36 7.90 9.03 1.59
first_fit 2t 2.73 10.62 12.40 13.56 14.54 16.46 19.46 4.88
ghost_tree 2t 8.05 8.42 8.55 8.57 8.62 8.92 10.48 0.46
segregated 2t 1.50 6.00 6.63 7.20 7.56 8.53 10.28 2.19
first_fit 4t 2.98 9.61 12.35 13.35 14.19 16.72 27.93 5.70
ghost_tree 4t 2.99 6.74 10.63 16.41 19.00 24.38 37.85 15.17
segregated 4t 1.19 5.60 6.38 6.78 7.47 8.57 10.09 2.62
first_fit 16t 2.44 10.38 12.14 12.83 14.61 22.92 25.98 10.50
ghost_tree 16t 8.45 10.30 10.60 10.89 11.10 11.51 14.85 1.03
segregated 16t 1.18 5.87 6.28 6.62 7.00 8.20 9.69 2.08

Median (p50) summary

vs_ff = first_fit / segregated, vs_gt = ghost_tree / segregated; > 1.00× means segregated is faster.

workload thr first_fit ghost_tree segregated vs_ff vs_gt
uniform 1 13.31 22.15 11.44 1.16× 1.94×
uniform 2 11.60 10.77 8.34 1.39× 1.29×
uniform 4 14.04 13.11 8.21 1.71× 1.60×
uniform 16 15.77 25.26 7.85 2.01× 3.22×
gamma-k2-t0.25 1 15.82 13.89 7.99 1.98× 1.74×
gamma-k2-t0.25 2 10.54 10.10 8.25 1.28× 1.22×
gamma-k2-t0.25 4 10.82 12.08 8.36 1.29× 1.44×
gamma-k2-t0.25 16 10.68 11.07 7.68 1.39× 1.44×
bimodal-s32-p0.2 1 13.29 17.45 7.19 1.85× 2.43×
bimodal-s32-p0.2 2 13.56 8.57 7.20 1.88× 1.19×
bimodal-s32-p0.2 4 13.35 16.41 6.78 1.97× 2.42×
bimodal-s32-p0.2 16 12.83 10.89 6.62 1.94× 1.64×

Geometric mean across all 12 cells: 1.62× vs first_fit, 1.72× vs ghost_tree; segregated wins 12/12 against each.

Verdict

Segregated has the lowest median in every cell, beating first_fit by 1.16–2.01× and ghost_tree
by 1.19–3.22×. Its median stays near 7–11 ms as threads scale 1→16, whereas ghost_tree degrades
(uniform 22→25 ms) and first_fit drifts upward, so the margin widens under concurrency (2.0×
first_fit, 3.2× ghost_tree at uniform/16t). The lead is largest on the skewed and bimodal
distributions it is built for. Its low per-op floor (min ~1.1–1.9 ms) comes from O(1)
class-indexed free-list pops, where first_fit rescans and ghost_tree walks its tree; the wider
IQR (2–5 ms) mixes those cheap reuse hits with occasional grow/extend ops, yet segregated's p80
still sits at or below the others' medians.

@williamwutq
williamwutq merged commit e411d62 into master Aug 13, 2026
16 checks passed
@williamwutq
williamwutq deleted the alloc branch August 13, 2026 21:02
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