Target: Reduce wrapper_env_cfg() overhead in malloc/free hot path - Strategy: Cache wrapper env configuration pointer in TLS - Approach: Fast pointer cache (TLS caches const wrapper_env_cfg_t*) Implementation: - core/box/wrapper_env_cache_env_box.h: ENV gate (HAKMEM_WRAP_ENV_CACHE) - core/box/wrapper_env_cache_box.h: TLS cache layer (wrapper_env_cfg_fast) - core/box/hak_wrappers.inc.h: Integration into malloc/free hot paths - ENV gate: HAKMEM_WRAP_ENV_CACHE=0/1 (default OFF) A/B Test Results (Mixed, 10-run, 20M iters): - Baseline (D2=0): 46.52M ops/s (avg), 46.47M ops/s (median) - Optimized (D2=1): 45.85M ops/s (avg), 45.98M ops/s (median) - Improvement: avg -1.44%, median -1.05% (DECISION: NO-GO) Analysis: - Regression cause: TLS cache adds overhead (branch + TLS access) - wrapper_env_cfg() is already minimal (pointer return after simple check) - Adding TLS caching layer makes it worse, not better - Branch prediction penalty outweighs any potential savings Cumulative Phase 2-3: - B3: +2.89%, B4: +1.47%, C3: +2.20% - D1: +1.06% (opt-in), D2: -1.44% (NO-GO) - Total: ~7.2% (excluding D2) Decision: FREEZE as research box (default OFF, regression confirmed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
3.3 KiB
3.3 KiB
Phase 3 C1: TLS Prefetch(Tiny alloc hot path)設計メモ
目的
Phase 2-3(B3/B4/C3)で「形(分岐・I-cache)」は勝ち形に寄った。 次は L1D miss / pointer chase を減らすための “軽い prefetch” を A/B する。
対象は policy ではなく、実際の alloc が触る TLS cache:
TinyUnifiedCache g_unified_cache[class](core/front/tiny_unified_cache.h)- 必要なら
cache->slots[]の先頭付近(head/tail 周辺)
非目標
- ルーティングやアルゴリズム変更はしない(prefetch は “ヒント” のみ)
- 常時ログは禁止(必要なら
HAKMEM_DEBUG_COUNTERSのみ) - “当たり前に速い” ことは期待しない(NO-GO なら即 freeze)
Box Theory(箱割り)
L0: Env(戻せる)
- 既存 ENV を使用:
HAKMEM_TINY_PREFETCH=0/1(default 0) - 目的: prefetch の on/off を即切替(回帰時に即戻せる)
L1: PrefetchBox(境界: 1 箇所)
責務: malloc の hot path で 1 回だけ prefetch を実行する。
実装場所は “入口” に固定(malloc_tiny_fast_for_class())。
候補 API(header-only で OK):
tiny_alloc_prefetch_tls_cache(class_idx, route_kind)route_kind == SMALL_ROUTE_LEGACYのときだけg_unified_cache[class_idx]を prefetch- 余計な prefetch を避ける(C6=MID 等で無駄撃ちしない)
実装指示(小パッチ順)
-
Prefetch 実装(最小)
- 追加箇所:
core/front/malloc_tiny_fast.hのmalloc_tiny_fast_for_class() - 条件:
tiny_env_cfg()->tiny_prefetch == 1route_kind == SMALL_ROUTE_LEGACY
- 実行:
__builtin_prefetch(&g_unified_cache[class_idx], 0, 3);
- 注意:
g_unified_cacheは TLS なので “当たる” 前提で入れすぎない(1 回だけ)
- 追加箇所:
-
Optional(勝ち筋が見えたら)
TinyUnifiedCache* cache = &g_unified_cache[class_idx];if (cache->slots) __builtin_prefetch(&cache->slots[cache->head], 0, 3);- ※ ただしロードが増えるので、まずは 1. の最小で A/B
-
ドキュメント
docs/specs/ENV_VARS_COMPLETE.mdにHAKMEM_TINY_PREFETCHを追記docs/analysis/PHASE3_CACHE_LOCALITY_NEXT_INSTRUCTIONS.mdの C1 をこの設計に合わせて更新
A/B(GO/NO-GO)
- Mixed(
HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE)10-run- 比較:
HAKMEM_TINY_PREFETCH=0vs=1 - GO: +1.0% 以上
- NO-GO: -1.0% 以下 → freeze
- ±1% は “研究箱維持”(デフォルトOFFのまま)
- 比較:
期待値の現実
prefetch は “刺さるときだけ刺さる”。 勝ち筋は「route 形の整理(B3/B4/C3)で instruction が減った結果、メモリ待ちが相対的に目立つ」状態になっていること。 もし勝てないなら、次は C2(metadata locality)へ進む。
結果(A/B)
判定: 🔬 NEUTRAL(研究箱維持、default OFF)
- Mixed 10-run:
HAKMEM_TINY_PREFETCH=0: avg 39.34MHAKMEM_TINY_PREFETCH=1: avg 39.20M(avg -0.34% / median +1.28%)
補足:
- 既存実装は “LEGACY 分岐の直前” に prefetch を入れており lead time が短い。
- 再挑戦するなら、prefetch 位置を より早い入口(
malloc_tiny_fast_for_class()冒頭など)に動かして A/B を取り直す。