diff --git a/AGENTS.md b/AGENTS.md index 50fef5b4..e4227483 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -235,6 +235,15 @@ Do / Don’t(壊れやすいパターンの禁止) - `[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)を優先的に直します。 diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 73bca1cb..79ee1be4 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -1,29 +1,38 @@ ## HAKMEM 状況メモ (2025-12-10 更新 / Mixed 基準ライン再固定) -### Phase S-FINAL: Mixed 16–1024B 現行ベースライン固定(C7-only v3 / front v3+LUT+fast classify ON) +### Phase BASELINE-LOCK: Mixed 16–1024B 現行ベースライン(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 により自動注入される値: - - `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_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 16–1024B 前提。未設定時は既定値を使用) - - その他: `HAKMEM_FREE_POLICY` / `HAKMEM_THP` / stats 系 ENV は未設定(デフォルトのまま)。 -- 結果(現 HEAD, Release, ユーザ環境での実測): - - HAKMEM baseline(C7 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 16–1024B のスループットは **約 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 程度のレンジに入っていることを確認する(マシン差は許容)。 +- 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 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_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024` +- 結果(現 HEAD, Release, 同一マシンで 2 回計測): + - v3 本命構成(上記): **33.7–33.9M ops/s** + - v4 強制(C7+C6 v4 + fast classify v4, v3 OFF, segment OFF): **32.0–32.5M ops/s** + - C7-only v4(C6 v1, v3 OFF, fast classify v4 ON): **≈33.0M ops/s** +- 決定: Mixed の本命構成は引き続き **C7-only v3**。v4 系は研究箱のまま OFF。健康診断の目安は `33–34M 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 16–1024B(C7-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 で見る」ルールを追記。 +- 現状ライン: + - Mixed(C7-only v3, ULTRA off): **33–34M ops/s**。 + - C6-heavy (`HAKMEM_PROFILE=C6_HEAVY_LEGACY_POOLV1`, flatten off): **≈10M ops/s**。今後は mid/pool 側から再設計して持ち直す想定(Tiny/SmallObject 経由で C6 を流さないのが前提)。 ### Phase FP1: Mixed 16–1024B madvise A/B(C7-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。 diff --git a/Makefile b/Makefile index 3b76fded..47b50ee6 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/core/box/tiny_c7_ultra_box.h b/core/box/tiny_c7_ultra_box.h new file mode 100644 index 00000000..c5513534 --- /dev/null +++ b/core/box/tiny_c7_ultra_box.h @@ -0,0 +1,25 @@ +// tiny_c7_ultra_box.h - C7 ULTRA TLS box (UF-2: TLS freelist, coldはv3を利用) +#pragma once + +#include +#include +#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 points(UF-1 は v3 C7 に委譲) +void* tiny_c7_ultra_alloc(size_t size); +void tiny_c7_ultra_free(void* ptr); diff --git a/core/box/tiny_c7_ultra_segment_box.h b/core/box/tiny_c7_ultra_segment_box.h new file mode 100644 index 00000000..ef1be3e4 --- /dev/null +++ b/core/box/tiny_c7_ultra_segment_box.h @@ -0,0 +1,34 @@ +// tiny_c7_ultra_segment_box.h - C7 ULTRA 専用セグメント Box(UF-3 足場) +#pragma once + +#include +#include + +// 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); diff --git a/core/tiny_c7_ultra.c b/core/tiny_c7_ultra.c new file mode 100644 index 00000000..e8a56ac3 --- /dev/null +++ b/core/tiny_c7_ultra.c @@ -0,0 +1,174 @@ +// tiny_c7_ultra.c - UF-2: C7 ULTRA TLS freelist (coldは既存 v3 を使用) + +#include +#include +#include +#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; +} diff --git a/core/tiny_c7_ultra_segment.c b/core/tiny_c7_ultra_segment.c new file mode 100644 index 00000000..23cdfec3 --- /dev/null +++ b/core/tiny_c7_ultra_segment.c @@ -0,0 +1,106 @@ +// tiny_c7_ultra_segment.c - C7 ULTRA 専用セグメント管理(UF-3) + +#include "box/tiny_c7_ultra_segment_box.h" + +#include +#include +#include +#include +#include + +// 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]; +} diff --git a/docs/analysis/TINY_C7_ULTRA_DESIGN.md b/docs/analysis/TINY_C7_ULTRA_DESIGN.md new file mode 100644 index 00000000..93162fb6 --- /dev/null +++ b/docs/analysis/TINY_C7_ULTRA_DESIGN.md @@ -0,0 +1,47 @@ +# TINY_C7_ULTRA_DESIGN + +## 目的 +- C7 (1024B) 向け mimalloc 型超高速パス(ULTRA)を用意し、Mixed 16–1024B を mimalloc の 5 割近辺まで寄せる。 +- 学習層や stats の仕組みは残しつつ、C7 同一スレッドのホットパスからは極力それらを排除する。 + +## 箱構造 +- Hot: TinyC7UltraBox(TLS freelist + C7 専用セグメントを握る同一スレッド専用箱) +- Cold: C7UltraSegmentBox(C7 専用セグメント管理。現段階では設計のみで未実装) +- 既存 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。