Add C7 ULTRA segment skeleton and TLS freelist

This commit is contained in:
Moe Charm (CI)
2025-12-10 22:19:32 +09:00
parent 49a1fe8416
commit bbb55b018a
8 changed files with 431 additions and 27 deletions

View File

@ -235,6 +235,15 @@ Do / Dont壊れやすいパターンの禁止
- `[POOL_V1_FLAT] alloc_tls_hit` / `free_tls_hit` が増えていることflatten 経路が効いている)。
- `free_fb_*`page_null / not_mine / otherは**少数**に収まっていること。増えてきたら owner 判定/lookup 側を優先トリアージする。
- C6 は Phase C6-FREEZE 中(標準では Tiny/SmallObject/ULTRA に載せない)
- 標準プロファイルMIXED_TINYV3_C7_SAFE / C6_HEAVY_LEGACY_POOLV1は C6 を mid/pool の通常クラスとして扱う。C6_HOT や smallheap(v3/v4)/ULTRA はすべて研究用の opt-in に限定。
- C6 を触るときは ENV_PROFILE_PRESETS.md の研究プリセットC6_SMALL_HEAP_V3_EXPERIMENT / C6_SMALL_HEAP_V4_EXPERIMENT など)から開始し、標準プリセットに混ぜ込まないこと。
- C7 ULTRA は研究箱ENV で必ず ON/OFF
- `HAKMEM_TINY_C7_ULTRA_ENABLED` で明示 opt-in。デフォルトは OFF。
- UF-3 以降は 2MiB セグメント64KiB ページ, mask 判定)上で carve/push。セグメント外の ptr は必ず既存 v3 free にフォールバックすること。
- ON/OFF の前後で必ず健康診断ランを 1 回ずつ取り、差分が出たらまず ULTRA 側を疑う。
- 一般ルール(壊れたらまず健康診断ラン)
- Tiny / Superslab / Pool に手を入れたあと、まず上記の健康診断ランを 1 回だけ回してから長尺ベンチ・本番 A/B に進んでください。
- 健康診断ランが落ちる場合は **新しい最適化を積む前に** Box 境界ptr 分類 / Superslab OS Box / Pool v1 flatten Boxを優先的に直します。

View File

@ -1,29 +1,38 @@
## HAKMEM 状況メモ (2025-12-10 更新 / Mixed 基準ライン再固定)
### Phase S-FINAL: Mixed 161024B 現行ベースライン固定C7-only v3 / front v3+LUT+fast classify ON
### Phase BASELINE-LOCK: Mixed 161024B 現行ベースラインC7-only v3 / front v3+LUT+fast classify v3
- ベンチ: `./bench_random_mixed_hakmem 1000000 400 1`1 thread, ws=400, iters=1M, seed=1
- ENV:
- プリセット: `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE`
- bench_profile により自動注入される値:
- ENV(プリセット `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE` で自動注入されるものを前提):
- `HAKMEM_TINY_HEAP_PROFILE=C7_SAFE`
- `HAKMEM_TINY_C7_HOT=1`
- `HAKMEM_TINY_HOTHEAP_V2=0`
- `HAKMEM_SMALL_HEAP_V3_ENABLED=1`
- `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80`C7-only SmallObject v3
- `HAKMEM_SMALL_HEAP_V3_ENABLED=1` / `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80`C7-only v3
- `HAKMEM_SMALL_HEAP_V4_ENABLED=0` / `HAKMEM_SMALL_HEAP_V4_CLASSES=0x0`
- `HAKMEM_TINY_PTR_FAST_CLASSIFY_ENABLED=1` / `HAKMEM_TINY_PTR_FAST_CLASSIFY_V4_ENABLED=0`
- `HAKMEM_SMALL_SEGMENT_V4_ENABLED=0`
- `HAKMEM_POOL_V2_ENABLED=0`
- `HAKMEM_TINY_FRONT_V3_ENABLED=1`
- `HAKMEM_TINY_FRONT_V3_LUT_ENABLED=1`
- `HAKMEM_TINY_PTR_FAST_CLASSIFY_ENABLED=1`
- サイズ範囲: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024`Mixed 161024B 前提。未設定時は既定値を使用)
- その他: `HAKMEM_FREE_POLICY` / `HAKMEM_THP` / stats 系 ENV は未設定(デフォルトのまま)。
- 結果(現 HEAD, Release, ユーザ環境での実測):
- HAKMEM baselineC7 header dedup OFF: **44,384,651 ops/s**
- HAKMEM + `HAKMEM_TINY_C7_HEADER_DEDUP_ENABLED=1`: **44,303,895 ops/s**(約 -0.2%、誤差レンジ内)
- メモ:
- 一時的に同プロファイルで ~36M ops/s まで落ち込んでいたが、Tiny front v3 snapshot の遅延・LUT 判定の整理・C7 ヘッダまわりの配置見直しにより、Mixed 161024B のスループットは **約 44M ops/s レベル** に戻っている。
- C7 ヘッダ再書き込み抑制dedupは ON/OFF いずれもほぼ同等で、現状は安全な実験箱として ENV ゲート付きのまま維持(デフォルトは OFF
- 以降の最適化はこの Phase S-FINAL を基準ラインとして扱い、A/B は必ず `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE` 前提で比較する(過去の別プロファイル・別ビルドの数値とは直接比較しない)
- Mixed の「健康診断 run」として、少なくとも `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE ./bench_random_mixed_hakmem 1000000 400 1` を 1 本通し、segv/assert なし・スループットが 40〜45M ops/s 程度のレンジに入っていることを確認する(マシン差は許容)
- `HAKMEM_TINY_FRONT_V3_ENABLED=1` / `HAKMEM_TINY_FRONT_V3_LUT_ENABLED=1`
- サイズ範囲: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024`
- 結果(現 HEAD, Release, 同一マシンで 2 回計測):
- v3 本命構成(上記): **33.733.9M ops/s**
- v4 強制C7+C6 v4 + fast classify v4, v3 OFF, segment OFF: **32.032.5M ops/s**
- C7-only v4C6 v1, v3 OFF, fast classify v4 ON: **≈33.0M ops/s**
- 決定: Mixed の本命構成は引き続き **C7-only v3**。v4 系は研究箱のまま OFF。健康診断の目安は `3334M ops/s / segvなし`
- 備考: このセクション以降の古い数値44M など)は過去フェーズの記録であり、現 HEAD とは一致しない。A/B は必ずこの Phase BASELINE-LOCK を基準に実施する。
### Phase UF-0〜UF-2: C7 ULTRA Fast Path段階的に箱化中
- UF-0: `docs/analysis/TINY_C7_ULTRA_DESIGN.md` に設計をまとめ、ULTRA は C7 専用セグメントを使う別箱Hot: TinyC7UltraBox, Cold: C7UltraSegmentBoxと定義。UF-1 ではまだページ供給を持たず v3 に委譲する stub で進める方針を確定
- UF-1: `core/box/tiny_c7_ultra_box.h` / `core/tiny_c7_ultra.c` を追加。ENV `HAKMEM_TINY_C7_ULTRA_ENABLED`(デフォルト OFFで front から C7 ULTRA stub を経由し、内部では既存 C7 v3 の so_alloc/so_free を呼ぶだけで挙動・性能は不変
- UF-2: ULTRA TLS に自前 freelist と C7 ページジオメトリを持たせ、C7 v3 ColdIface から 1 ページ lease→自前 carve→ヘッダ書きで返すホットパスを実装。範囲外/失敗は so_alloc/so_free へ即フォールバック。Mixed 161024BC7-only v3 本線, ws=400, 1Mで ULTRA ON は OFF 比でおおよそ +9% 程度の改善を確認segv/assert なし。UF-3 以降で専用 2MiB セグメントmask 判定による完全ヘッダレス化を予定
### Phase C6-FREEZE: C6 は mid/pool の普通クラスに固定(研究箱に退避)
- 目的: C6 を Tiny/SmallObject/ULTRA で特別扱いしないのを標準とし、C6 v3/v4/ULTRA/flatten はすべて ENV opt-in の研究箱に戻す。
- 変更:
- プリセット `MIXED_TINYV3_C7_SAFE` / `C6_HEAVY_LEGACY_POOLV1` から C6_HOT を外し、SmallObject クラスマスクのデフォルトは C7-only (`0x80`) に統一。C6_smallheap 用の研究プリセットを別枠で用意(`C6_SMALL_HEAP_V3_EXPERIMENT` / `C6_SMALL_HEAP_V4_EXPERIMENT`)。
- AGENTS に「C6 専用最適化は研究箱のみ、標準ラインは mid/pool で見る」ルールを追記。
- 現状ライン:
- MixedC7-only v3, ULTRA off: **3334M ops/s**
- C6-heavy (`HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1`, flatten off): **≈10M ops/s**。今後は mid/pool 側から再設計して持ち直す想定Tiny/SmallObject 経由で C6 を流さないのが前提)。
### Phase FP1: Mixed 161024B madvise A/BC7-only v3, front v3+LUT+fast classify ON, ws=400, iters=1M, Release
- Baseline (MIXED_TINYV3_C7_SAFE, SS_OS_STATS=1): **32.76M ops/s**`[SS_OS_STATS] madvise=4 madvise_enomem=1 madvise_disabled=1`warmup で ENOMEM→madvise 停止。perf: task-clock 50.88ms / minor-faults 6,742 / user 35.3ms / sys 16.2ms。

View File

@ -218,12 +218,12 @@ LDFLAGS += $(EXTRA_LDFLAGS)
# Targets
TARGET = test_hakmem
OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/free_publish_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o core/tiny_alloc_fast_push.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o
OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/free_publish_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o core/tiny_alloc_fast_push.o core/tiny_c7_ultra_segment.o core/tiny_c7_ultra.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o
OBJS = $(OBJS_BASE)
# Shared library
SHARED_LIB = libhakmem.so
SHARED_OBJS = hakmem_shared.o hakmem_config_shared.o hakmem_tiny_config_shared.o hakmem_ucb1_shared.o hakmem_bigcache_shared.o hakmem_pool_shared.o hakmem_l25_pool_shared.o hakmem_site_rules_shared.o hakmem_tiny_shared.o core/box/ss_allocation_box_shared.o superslab_stats_shared.o superslab_cache_shared.o superslab_ace_shared.o superslab_slab_shared.o superslab_backend_shared.o core/superslab_head_stub_shared.o hakmem_smallmid_shared.o core/box/superslab_expansion_box_shared.o core/box/integrity_box_shared.o core/box/mailbox_box_shared.o core/box/front_gate_box_shared.o core/box/front_gate_classifier_shared.o core/box/free_publish_box_shared.o core/box/capacity_box_shared.o core/box/carve_push_box_shared.o core/box/prewarm_box_shared.o core/box/ss_hot_prewarm_box_shared.o core/box/front_metrics_box_shared.o core/box/bench_fast_box_shared.o core/box/ss_addr_map_box_shared.o core/box/slab_recycling_box_shared.o core/box/pagefault_telemetry_box_shared.o core/box/tiny_sizeclass_hist_box_shared.o core/box/tiny_env_box_shared.o core/box/tiny_route_box_shared.o core/box/tiny_page_box_shared.o core/box/tiny_class_policy_box_shared.o core/box/tiny_class_stats_box_shared.o core/box/tiny_policy_learner_box_shared.o core/box/ss_budget_box_shared.o core/box/tiny_mem_stats_box_shared.o core/box/wrapper_env_box_shared.o core/box/madvise_guard_box_shared.o core/box/libm_reloc_guard_box_shared.o core/page_arena_shared.o core/front/tiny_unified_cache_shared.o core/tiny_alloc_fast_push_shared.o core/link_stubs_shared.o core/tiny_failfast_shared.o tiny_sticky_shared.o tiny_remote_shared.o tiny_publish_shared.o tiny_debug_ring_shared.o hakmem_tiny_magazine_shared.o hakmem_tiny_stats_shared.o hakmem_tiny_sfc_shared.o hakmem_tiny_query_shared.o hakmem_tiny_rss_shared.o hakmem_tiny_registry_shared.o hakmem_tiny_remote_target_shared.o hakmem_tiny_bg_spill_shared.o tiny_adaptive_sizing_shared.o hakmem_super_registry_shared.o hakmem_shared_pool_shared.o hakmem_shared_pool_acquire_shared.o hakmem_shared_pool_release_shared.o hakmem_elo_shared.o hakmem_batch_shared.o hakmem_p2_shared.o hakmem_sizeclass_dist_shared.o hakmem_evo_shared.o hakmem_debug_shared.o hakmem_sys_shared.o hakmem_whale_shared.o hakmem_policy_shared.o hakmem_ace_shared.o hakmem_ace_stats_shared.o hakmem_ace_controller_shared.o hakmem_ace_metrics_shared.o hakmem_ace_ucb1_shared.o hakmem_prof_shared.o hakmem_learner_shared.o hakmem_size_hist_shared.o hakmem_learn_log_shared.o hakmem_syscall_shared.o tiny_fastcache_shared.o core/box/super_reg_box_shared.o core/box/shared_pool_box_shared.o core/box/remote_side_box_shared.o core/tiny_destructors_shared.o
SHARED_OBJS = hakmem_shared.o hakmem_config_shared.o hakmem_tiny_config_shared.o hakmem_ucb1_shared.o hakmem_bigcache_shared.o hakmem_pool_shared.o hakmem_l25_pool_shared.o hakmem_site_rules_shared.o hakmem_tiny_shared.o core/box/ss_allocation_box_shared.o superslab_stats_shared.o superslab_cache_shared.o superslab_ace_shared.o superslab_slab_shared.o superslab_backend_shared.o core/superslab_head_stub_shared.o hakmem_smallmid_shared.o core/box/superslab_expansion_box_shared.o core/box/integrity_box_shared.o core/box/mailbox_box_shared.o core/box/front_gate_box_shared.o core/box/front_gate_classifier_shared.o core/box/free_publish_box_shared.o core/box/capacity_box_shared.o core/box/carve_push_box_shared.o core/box/prewarm_box_shared.o core/box/ss_hot_prewarm_box_shared.o core/box/front_metrics_box_shared.o core/box/bench_fast_box_shared.o core/box/ss_addr_map_box_shared.o core/box/slab_recycling_box_shared.o core/box/pagefault_telemetry_box_shared.o core/box/tiny_sizeclass_hist_box_shared.o core/box/tiny_env_box_shared.o core/box/tiny_route_box_shared.o core/box/tiny_page_box_shared.o core/box/tiny_class_policy_box_shared.o core/box/tiny_class_stats_box_shared.o core/box/tiny_policy_learner_box_shared.o core/box/ss_budget_box_shared.o core/box/tiny_mem_stats_box_shared.o core/box/wrapper_env_box_shared.o core/box/madvise_guard_box_shared.o core/box/libm_reloc_guard_box_shared.o core/page_arena_shared.o core/front/tiny_unified_cache_shared.o core/tiny_alloc_fast_push_shared.o core/tiny_c7_ultra_segment_shared.o core/tiny_c7_ultra_shared.o core/link_stubs_shared.o core/tiny_failfast_shared.o tiny_sticky_shared.o tiny_remote_shared.o tiny_publish_shared.o tiny_debug_ring_shared.o hakmem_tiny_magazine_shared.o hakmem_tiny_stats_shared.o hakmem_tiny_sfc_shared.o hakmem_tiny_query_shared.o hakmem_tiny_rss_shared.o hakmem_tiny_registry_shared.o hakmem_tiny_remote_target_shared.o hakmem_tiny_bg_spill_shared.o tiny_adaptive_sizing_shared.o hakmem_super_registry_shared.o hakmem_shared_pool_shared.o hakmem_shared_pool_acquire_shared.o hakmem_shared_pool_release_shared.o hakmem_elo_shared.o hakmem_batch_shared.o hakmem_p2_shared.o hakmem_sizeclass_dist_shared.o hakmem_evo_shared.o hakmem_debug_shared.o hakmem_sys_shared.o hakmem_whale_shared.o hakmem_policy_shared.o hakmem_ace_shared.o hakmem_ace_stats_shared.o hakmem_ace_controller_shared.o hakmem_ace_metrics_shared.o hakmem_ace_ucb1_shared.o hakmem_prof_shared.o hakmem_learner_shared.o hakmem_size_hist_shared.o hakmem_learn_log_shared.o hakmem_syscall_shared.o tiny_fastcache_shared.o core/box/super_reg_box_shared.o core/box/shared_pool_box_shared.o core/box/remote_side_box_shared.o core/tiny_destructors_shared.o
# Pool TLS Phase 1 (enable with POOL_TLS_PHASE1=1)
ifeq ($(POOL_TLS_PHASE1),1)
@ -250,7 +250,7 @@ endif
# Benchmark targets
BENCH_HAKMEM = bench_allocators_hakmem
BENCH_SYSTEM = bench_allocators_system
BENCH_HAKMEM_OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/free_publish_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/c7_meta_used_counter_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o core/tiny_alloc_fast_push.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o bench_allocators_hakmem.o
BENCH_HAKMEM_OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/free_publish_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/c7_meta_used_counter_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o core/tiny_alloc_fast_push.o core/tiny_c7_ultra_segment.o core/tiny_c7_ultra.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o bench_allocators_hakmem.o
BENCH_HAKMEM_OBJS = $(BENCH_HAKMEM_OBJS_BASE)
ifeq ($(POOL_TLS_PHASE1),1)
BENCH_HAKMEM_OBJS += pool_tls.o pool_refill.o pool_tls_arena.o pool_tls_registry.o pool_tls_remote.o
@ -427,7 +427,7 @@ test-box-refactor: box-refactor
./larson_hakmem 10 8 128 1024 1 12345 4
# Phase 4: Tiny Pool benchmarks (properly linked with hakmem)
TINY_BENCH_OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/free_publish_box.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/c7_meta_used_counter_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/tiny_alloc_fast_push.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o core/smallobject_hotbox_v3.o core/smallobject_hotbox_v4.o
TINY_BENCH_OBJS_BASE = hakmem.o hakmem_config.o hakmem_tiny_config.o hakmem_ucb1.o hakmem_bigcache.o hakmem_pool.o hakmem_l25_pool.o hakmem_site_rules.o hakmem_tiny.o core/box/ss_allocation_box.o superslab_stats.o superslab_cache.o superslab_ace.o superslab_slab.o superslab_backend.o core/superslab_head_stub.o hakmem_smallmid.o core/box/superslab_expansion_box.o core/box/integrity_box.o core/box/mailbox_box.o core/box/front_gate_box.o core/box/front_gate_classifier.o core/box/free_publish_box.o core/box/capacity_box.o core/box/carve_push_box.o core/box/prewarm_box.o core/box/ss_hot_prewarm_box.o core/box/front_metrics_box.o core/box/bench_fast_box.o core/box/ss_addr_map_box.o core/box/slab_recycling_box.o core/box/pagefault_telemetry_box.o core/box/tiny_sizeclass_hist_box.o core/box/tiny_env_box.o core/box/tiny_route_box.o core/box/tiny_page_box.o core/box/tiny_class_policy_box.o core/box/tiny_class_stats_box.o core/box/tiny_policy_learner_box.o core/box/ss_budget_box.o core/box/tiny_mem_stats_box.o core/box/c7_meta_used_counter_box.o core/box/wrapper_env_box.o core/box/madvise_guard_box.o core/box/libm_reloc_guard_box.o core/box/ptr_trace_box.o core/box/link_missing_stubs.o core/box/super_reg_box.o core/box/shared_pool_box.o core/box/remote_side_box.o core/page_arena.o core/front/tiny_unified_cache.o tiny_sticky.o tiny_remote.o tiny_publish.o tiny_debug_ring.o hakmem_tiny_magazine.o hakmem_tiny_stats.o hakmem_tiny_sfc.o hakmem_tiny_query.o hakmem_tiny_rss.o hakmem_tiny_registry.o hakmem_tiny_remote_target.o hakmem_tiny_bg_spill.o tiny_adaptive_sizing.o hakmem_super_registry.o hakmem_shared_pool.o hakmem_shared_pool_acquire.o hakmem_shared_pool_release.o hakmem_elo.o hakmem_batch.o hakmem_p2.o hakmem_sizeclass_dist.o hakmem_evo.o hakmem_debug.o hakmem_sys.o hakmem_whale.o hakmem_policy.o hakmem_ace.o hakmem_ace_stats.o hakmem_prof.o hakmem_learner.o hakmem_size_hist.o hakmem_learn_log.o hakmem_syscall.o hakmem_ace_metrics.o hakmem_ace_ucb1.o hakmem_ace_controller.o tiny_fastcache.o core/tiny_alloc_fast_push.o core/tiny_c7_ultra_segment.o core/tiny_c7_ultra.o core/link_stubs.o core/tiny_failfast.o core/tiny_destructors.o core/smallobject_hotbox_v3.o core/smallobject_hotbox_v4.o
TINY_BENCH_OBJS = $(TINY_BENCH_OBJS_BASE)
ifeq ($(POOL_TLS_PHASE1),1)
TINY_BENCH_OBJS += pool_tls.o pool_refill.o core/pool_tls_arena.o pool_tls_registry.o pool_tls_remote.o

View File

@ -0,0 +1,25 @@
// tiny_c7_ultra_box.h - C7 ULTRA TLS box (UF-2: TLS freelist, coldはv3を利用)
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "tiny_c7_ultra_segment_box.h"
// Hot box: per-thread TLS context (UF-1 ではフィールドは未使用だが将来の ULTRA 用に定義)
typedef struct tiny_c7_ultra_tls_t {
void* page_base; // ULTRA 専用 C7 ページ基底
size_t block_size; // C7 ブロックサイズ
uint32_t capacity; // ページ内スロット数
uint32_t used; // 現在使用中スロット
void* freelist; // ULTRA 用 freelist 先頭
uint32_t page_idx; // セグメント内ページ index
tiny_c7_ultra_segment_t* seg; // 所有セグメント
tiny_c7_ultra_page_meta_t* page_meta; // 現在のページメタ
} tiny_c7_ultra_tls_t;
// TLS accessor
tiny_c7_ultra_tls_t* tiny_c7_ultra_tls_get(void);
// ULTRA alloc/free entry pointsUF-1 は v3 C7 に委譲)
void* tiny_c7_ultra_alloc(size_t size);
void tiny_c7_ultra_free(void* ptr);

View File

@ -0,0 +1,34 @@
// tiny_c7_ultra_segment_box.h - C7 ULTRA 専用セグメント BoxUF-3 足場)
#pragma once
#include <stddef.h>
#include <stdint.h>
// 1ページぶんのメタデータULTRA 専用なので軽量)
typedef struct tiny_c7_ultra_page_meta {
void* freelist;
uint32_t used;
uint32_t capacity;
} tiny_c7_ultra_page_meta_t;
typedef struct tiny_c7_ultra_segment {
void* base;
size_t seg_size;
size_t page_size;
uint32_t num_pages;
tiny_c7_ultra_page_meta_t* pages;
} tiny_c7_ultra_segment_t;
// 1 セグメントを確保UF-3 は TLS で 1 枚だけ持てば十分)
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_acquire(void);
// セグメントを解放UF-3 では未使用だが API として残す)
void tiny_c7_ultra_segment_release(tiny_c7_ultra_segment_t* seg);
// ptr が ULTRA セグメント内か判定(セグメントに該当しない場合は NULL
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_from_ptr(void* p);
// ptr に対応するページメタを取得(セグメント外なら NULL
tiny_c7_ultra_page_meta_t* tiny_c7_ultra_page_of(void* p,
tiny_c7_ultra_segment_t** out_seg,
uint32_t* out_page_idx);

174
core/tiny_c7_ultra.c Normal file
View File

@ -0,0 +1,174 @@
// tiny_c7_ultra.c - UF-2: C7 ULTRA TLS freelist (coldは既存 v3 を使用)
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "box/tiny_c7_ultra_box.h"
#include "box/smallobject_hotbox_v3_box.h"
#include "box/tiny_geometry_box.h"
#include "tiny_region_id.h"
#include "box/tiny_c7_ultra_segment_box.h"
static __thread tiny_c7_ultra_tls_t g_tiny_c7_ultra_tls;
static inline void tiny_c7_ultra_clear(tiny_c7_ultra_tls_t* tls) {
tls->page_base = NULL;
tls->block_size = 0;
tls->capacity = 0;
tls->used = 0;
tls->freelist = NULL;
tls->page_idx = 0;
tls->page_meta = NULL;
}
tiny_c7_ultra_tls_t* tiny_c7_ultra_tls_get(void) {
return &g_tiny_c7_ultra_tls;
}
// セグメントから C7 ページを 1 枚借りて自前で carve する
static bool tiny_c7_ultra_lease_page(tiny_c7_ultra_tls_t* tls) {
tiny_c7_ultra_segment_t* seg = tls->seg;
if (!seg) {
seg = tiny_c7_ultra_segment_acquire();
if (!seg) return false;
tls->seg = seg;
}
size_t block_sz = tls->block_size ? tls->block_size
: (size_t)tiny_stride_for_class(7);
if (block_sz == 0) return false;
uint32_t capacity = (uint32_t)(seg->page_size / block_sz);
if (capacity == 0) return false;
// 空きページを 1 枚だけ拾うUF-3 では最初の空きを線形探索)
uint32_t chosen = seg->num_pages;
for (uint32_t i = 0; i < seg->num_pages; i++) {
tiny_c7_ultra_page_meta_t* pm = &seg->pages[i];
if (pm->capacity == 0 || pm->used == 0) {
chosen = i;
break;
}
}
if (chosen == seg->num_pages) {
return false;
}
tiny_c7_ultra_page_meta_t* page = &seg->pages[chosen];
uint8_t* base = (uint8_t*)seg->base + ((size_t)chosen * seg->page_size);
// freelist を自前で carve
void* head = NULL;
for (int i = (int)capacity - 1; i >= 0; i--) {
uint8_t* blk = base + ((size_t)i * block_sz);
*(void**)blk = head;
head = blk;
}
if (!head) {
return false;
}
page->freelist = head;
page->capacity = capacity;
page->used = 0;
tls->page_base = base;
tls->block_size = block_sz;
tls->capacity = capacity;
tls->used = 0;
tls->freelist = head;
tls->page_idx = chosen;
tls->page_meta = page;
return true;
}
void* tiny_c7_ultra_alloc(size_t size) {
(void)size; // C7 専用のため未使用
tiny_c7_ultra_tls_t* tls = tiny_c7_ultra_tls_get();
// 1) freelist hit
void* p = tls->freelist;
if (__builtin_expect(p != NULL, 1)) {
void* next = *(void**)p;
tls->freelist = next;
if (tls->page_meta) {
tls->page_meta->freelist = next;
if (tls->page_meta->used < tls->page_meta->capacity) {
tls->page_meta->used++;
}
}
if (tls->used < tls->capacity) {
tls->used++;
}
return tiny_region_id_write_header(p, 7);
}
// 2) lease page from existing v3 cold path
if (!tiny_c7_ultra_lease_page(tls)) {
// safety fallback to v3
return so_alloc(7);
}
p = tls->freelist;
if (__builtin_expect(p == NULL, 0)) {
return so_alloc(7);
}
void* next = *(void**)p;
tls->freelist = next;
if (tls->page_meta) {
tls->page_meta->freelist = next;
if (tls->page_meta->used < tls->page_meta->capacity) {
tls->page_meta->used++;
}
}
if (tls->used < tls->capacity) {
tls->used++;
}
return tiny_region_id_write_header(p, 7);
}
void tiny_c7_ultra_free(void* ptr) {
tiny_c7_ultra_tls_t* tls = tiny_c7_ultra_tls_get();
if (!ptr) {
so_free(7, ptr);
return;
}
tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(ptr);
if (!seg) {
so_free(7, ptr);
return;
}
uint32_t page_idx = 0;
tiny_c7_ultra_page_meta_t* page = tiny_c7_ultra_page_of(ptr, &seg, &page_idx);
if (!page) {
so_free(7, ptr);
return;
}
const size_t block_sz = tls->block_size ? tls->block_size
: (size_t)tiny_stride_for_class(7);
const uint32_t cap = page->capacity ? page->capacity
: (uint32_t)(seg->page_size / block_sz);
uintptr_t base = (uintptr_t)seg->base + ((size_t)page_idx * seg->page_size);
uintptr_t paddr = (uintptr_t)ptr;
size_t span = block_sz * (size_t)cap;
if (paddr < base || paddr >= base + span || ((paddr - base) % block_sz) != 0) {
so_free(7, ptr);
return;
}
*(void**)ptr = page->freelist;
page->freelist = ptr;
if (page->used > 0) {
page->used--;
}
tls->page_meta = page;
tls->page_idx = page_idx;
tls->page_base = (void*)base;
tls->capacity = cap;
tls->block_size = block_sz;
tls->freelist = page->freelist;
tls->used = page->used;
}

View File

@ -0,0 +1,106 @@
// tiny_c7_ultra_segment.c - C7 ULTRA 専用セグメント管理UF-3
#include "box/tiny_c7_ultra_segment_box.h"
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
// 2MiB セグメントを 64KiB ページに分割C7 専用、pow2 で mask しやすく)
#define TINY_C7_ULTRA_SEG_SIZE ((size_t)(2 * 1024 * 1024))
#define TINY_C7_ULTRA_PAGE_SIZE ((size_t)(64 * 1024))
static __thread tiny_c7_ultra_segment_t* g_ultra_seg;
static inline void tiny_c7_ultra_segment_clear(tiny_c7_ultra_segment_t* seg) {
if (!seg) return;
seg->base = NULL;
seg->seg_size = 0;
seg->page_size = 0;
seg->num_pages = 0;
seg->pages = NULL;
}
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_acquire(void) {
if (g_ultra_seg) {
return g_ultra_seg;
}
tiny_c7_ultra_segment_t* seg =
(tiny_c7_ultra_segment_t*)calloc(1, sizeof(tiny_c7_ultra_segment_t));
if (!seg) {
return NULL;
}
seg->seg_size = TINY_C7_ULTRA_SEG_SIZE;
seg->page_size = TINY_C7_ULTRA_PAGE_SIZE;
seg->num_pages = (uint32_t)(seg->seg_size / seg->page_size);
seg->pages = (tiny_c7_ultra_page_meta_t*)calloc(seg->num_pages,
sizeof(tiny_c7_ultra_page_meta_t));
if (!seg->pages) {
free(seg);
return NULL;
}
void* base = mmap(NULL, seg->seg_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (base == MAP_FAILED) {
int saved = errno;
free(seg->pages);
free(seg);
(void)saved;
return NULL;
}
seg->base = base;
g_ultra_seg = seg;
return seg;
}
void tiny_c7_ultra_segment_release(tiny_c7_ultra_segment_t* seg) {
if (!seg) return;
if (seg->base && seg->seg_size) {
munmap(seg->base, seg->seg_size);
}
free(seg->pages);
if (seg == g_ultra_seg) {
g_ultra_seg = NULL;
}
free(seg);
}
tiny_c7_ultra_segment_t* tiny_c7_ultra_segment_from_ptr(void* p) {
tiny_c7_ultra_segment_t* seg = g_ultra_seg;
if (!seg || !seg->base || seg->seg_size == 0) return NULL;
uintptr_t base = (uintptr_t)seg->base;
uintptr_t addr = (uintptr_t)p;
if (addr < base || addr >= base + seg->seg_size) {
return NULL;
}
return seg;
}
tiny_c7_ultra_page_meta_t* tiny_c7_ultra_page_of(void* p,
tiny_c7_ultra_segment_t** out_seg,
uint32_t* out_page_idx) {
tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(p);
if (!seg) {
return NULL;
}
uintptr_t base = (uintptr_t)seg->base;
uintptr_t addr = (uintptr_t)p;
size_t offset = (size_t)(addr - base);
uint32_t idx = (uint32_t)(offset / seg->page_size);
if (idx >= seg->num_pages) {
return NULL;
}
if (out_seg) {
*out_seg = seg;
}
if (out_page_idx) {
*out_page_idx = idx;
}
return &seg->pages[idx];
}

View File

@ -0,0 +1,47 @@
# TINY_C7_ULTRA_DESIGN
## 目的
- C7 (1024B) 向け mimalloc 型超高速パスULTRAを用意し、Mixed 161024B を mimalloc の 5 割近辺まで寄せる。
- 学習層や stats の仕組みは残しつつ、C7 同一スレッドのホットパスからは極力それらを排除する。
## 箱構造
- Hot: TinyC7UltraBoxTLS freelist + C7 専用セグメントを握る同一スレッド専用箱)
- Cold: C7UltraSegmentBoxC7 専用セグメント管理。現段階では設計のみで未実装)
- 既存 Cold: Superslab / WarmPool / Guard / Remote / Stats は既存の箱のまま。ULTRA は原則触らない。
## 決定事項(芯)
1. C7 専用ページ源
- ULTRA は「C7 専用セグメント」からページを取る(将来は mmap で 2〜4MiB 単位)。
- v3/v4/Tiny v1 が握る C7 ページとは混ざらない前提。
- UF-1 時点では C7UltraSegmentBox は未実装で、C7 ページ供給は既存 v3 経由の stub とする。
2. free 時の ptr→page
- ULTRA が扱う C7 ページは C7 専用セグメント上にのみ存在すると決める。
- 将来像:
- seg = p & ~(SEG_SIZE-1) で segment 基底。
- seg が ULTRA 管理表にあれば offset / page_idx / page_meta から class=7 を取得し、ヘッダなしで freelist push。
- 管理表に無ければ既存 v3/v4 freeヘッダありにフォールバック。
3. ULTRA と v3/v4 の責務分離
- ULTRA ON: C7 アロケーションはすべて ULTRA 管理v3/v4 は C7 ページを新規に取らない)。
- ULTRA OFF: C7 は v3現行本命か v4 が処理する。
- free: 「まず ULTRA セグメントか」を判定し、ULTRA 管理外なら常に v3/v4 free へ落とすオーバーレイ構造。
- Remote/cross-thread free は ULTRA 非対応。ULTRA は同一スレッド C7 専用 TLS box として設計。
4. Fail-Fast ポリシー
- ULTRA が扱わないポインタは必ず v3/v4 側でヘッダ検証・範囲チェックを行う。
- ULTRA 内部不整合(将来フェーズ)は statsワンショットログで可視化し、可能なら v3/v4 へフォールバック。
## セグメント前提UF-3 仕様)
- SEG_SIZE: 2MiB (pow2)。seg_base = ptr & ~(SEG_SIZE-1) で判定可能にする。
- セグメント構造(イメージ):
- base, seg_size (=2MiB), page_size (=TINY_PAGE_SIZE 想定), num_pages (=seg_size/page_size)
- page_meta[num_pages]freelist/used/capacity だけを持つ軽量構造)
- free 時の判定:
- seg = p & ~(SEG_SIZE-1) で ULTRA 管理セグメントか確認。
- 管理外 → v3 freeヘッダ付き経路へフォールバック。
- 管理内 → page_idx = (p - seg_base) >> PAGE_SHIFT で page_meta を取得し、ヘッダ無しで freelist push。
- Remote/cross-thread free は UF-3 でも非対応(同一スレッド C7 専用のまま)。
## フェーズ
- UF-1: 箱・ENV・front フックだけ stub で入れる(中身は v3 C7 経由、挙動変化なし)。
- UF-2: ULTRA TLS freelist を実装C7 ページ 1 枚を TLS で握る。同一スレッドのみ。C7 ページ供給は当面 v3/v4 経由。
- UF-3: C7UltraSegmentBox を実装し、ptr→segment mask でヘッダレス free に寄せる(セグメント 1 枚のみでも可)。
- UF-4: pf/segment/学習層との統合を調整し、Mixed で本格的に A/B。