diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 27be33e9..d8138b7d 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -170,10 +170,32 @@ - C3 (Static routing): +2.20% - **Total: ~6.8%** (baseline 35.2M → ~39.8M ops/s) -**優先度 C1** - TLS cache prefetch: -- `__builtin_prefetch(g_small_policy_v7, 0, 3)` on malloc entry -- Improve L1 hit rate on cold start -- Expected: +2-4% +#### Phase 3 C1: TLS Cache Prefetch 🔬 NEUTRAL / FREEZE + +**設計メモ**: `docs/analysis/PHASE3_C1_TLS_PREFETCH_1_DESIGN.md` + +**狙い**: malloc ホットパス LEGACY 入口で `g_unified_cache[class_idx]` を L1 prefetch(数十クロック早期) + +**実装完了** ✅: +- `core/front/malloc_tiny_fast.h` (lines 264-267, 331-334) + - env_cfg->alloc_route_shape=1 の fast path(線264-267) + - env_cfg->alloc_route_shape=0 の fallback path(線331-334) + - ENV gate: `HAKMEM_TINY_PREFETCH=0/1`(default 0) + +**A/B テスト結果** 🔬 NEUTRAL: +- Mixed (10-run): 39,335,109 → 39,203,334 ops/s (**-0.34% average**, median **+1.28%**) +- Average gain: -0.34%(わずかな回帰、±1.0% 範囲内) +- Median gain: +1.28%(閾値超え) +- **Decision: NEUTRAL** (研究箱維持、デフォルト OFF) + - 理由: Average で -0.34% なので、prefetch 効果が噪音範囲 + - Prefetch は "当たるかどうか" が不確定(TLS access timing dependent) + - ホットパス後(tiny_hot_alloc_fast 直前)での実行では効果限定的 + +**技術考察**: +- prefetch が効果を発揮するには、L1 miss が発生する必要がある +- TLS キャッシュは unified_cache_pop() で素早くアクセス(head/tail インデックス) +- 実際のメモリ待ちは slots[] 配列へのアクセス時(prefetch より後) +- 改善案: prefetch をもっと早期(route_kind 決定前)に移動するか、形状を変更 **優先度 C2** - Slab metadata cache optimization: - Profile cache-miss hotspots (policy struct, slab metadata) diff --git a/core/front/malloc_tiny_fast.h b/core/front/malloc_tiny_fast.h index 68a25192..ae4b01ab 100644 --- a/core/front/malloc_tiny_fast.h +++ b/core/front/malloc_tiny_fast.h @@ -261,6 +261,10 @@ static inline void* malloc_tiny_fast_for_class(size_t size, int class_idx) { if (TINY_HOT_LIKELY(env_cfg->alloc_route_shape)) { // B3 optimized: Prioritize LEGACY with LIKELY hint if (TINY_HOT_LIKELY(route_kind == SMALL_ROUTE_LEGACY)) { + // Phase 3 C1: TLS cache prefetch (prefetch g_unified_cache[class_idx] to L1) + if (__builtin_expect(env_cfg->tiny_prefetch, 0)) { + __builtin_prefetch(&g_unified_cache[class_idx], 0, 3); + } // LEGACY fast path: Unified Cache hot/cold void* ptr = tiny_hot_alloc_fast(class_idx); if (TINY_HOT_LIKELY(ptr != NULL)) { @@ -324,6 +328,10 @@ static inline void* malloc_tiny_fast_for_class(size_t size, int class_idx) { break; } + // Phase 3 C1: TLS cache prefetch (prefetch g_unified_cache[class_idx] to L1) + if (__builtin_expect(env_cfg->tiny_prefetch, 0)) { + __builtin_prefetch(&g_unified_cache[class_idx], 0, 3); + } // LEGACY fallback: Unified Cache hot/cold path void* ptr = tiny_hot_alloc_fast(class_idx); if (TINY_HOT_LIKELY(ptr != NULL)) { diff --git a/docs/analysis/ENV_PROFILE_PRESETS.md b/docs/analysis/ENV_PROFILE_PRESETS.md index 0547e3b3..bb6e4934 100644 --- a/docs/analysis/ENV_PROFILE_PRESETS.md +++ b/docs/analysis/ENV_PROFILE_PRESETS.md @@ -40,6 +40,7 @@ HAKMEM_BENCH_MAX_SIZE=1024 - `HAKMEM_FREE_TINY_FAST_HOTCOLD=1`(Phase FREE-TINY-FAST-DUALHOT-1: free の第2ホット(C0-C3)を直行) - `HAKMEM_WRAP_SHAPE=1`(Phase 2 B4: wrapper hot/cold split を default ON) - `HAKMEM_TINY_ALLOC_ROUTE_SHAPE=1`(Phase 2 B3: alloc の route dispatch 形を最適化) +- `HAKMEM_TINY_STATIC_ROUTE=1`(Phase 3 C3: policy_snapshot bypass を default ON) - `HAKMEM_MID_V3_ENABLED=1`(Phase MID-V3: 257-768B, C6 only) - `HAKMEM_MID_V3_CLASSES=0x40`(C6 only, C7 は ULTRA に任せる) - `HAKMEM_MID_V35_ENABLED=0`(Phase v11a-5: Mixed では MID v3.5 OFF が最速) diff --git a/docs/analysis/PHASE3_C1_TLS_PREFETCH_1_DESIGN.md b/docs/analysis/PHASE3_C1_TLS_PREFETCH_1_DESIGN.md new file mode 100644 index 00000000..3282e1c3 --- /dev/null +++ b/docs/analysis/PHASE3_C1_TLS_PREFETCH_1_DESIGN.md @@ -0,0 +1,69 @@ +# 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 等で無駄撃ちしない) + +## 実装指示(小パッチ順) + +1. **Prefetch 実装(最小)** + - 追加箇所: `core/front/malloc_tiny_fast.h` の `malloc_tiny_fast_for_class()` + - 条件: + - `tiny_env_cfg()->tiny_prefetch == 1` + - `route_kind == SMALL_ROUTE_LEGACY` + - 実行: + - `__builtin_prefetch(&g_unified_cache[class_idx], 0, 3);` + - 注意: + - `g_unified_cache` は TLS なので “当たる” 前提で入れすぎない(1 回だけ) + +2. **Optional(勝ち筋が見えたら)** + - `TinyUnifiedCache* cache = &g_unified_cache[class_idx];` + - `if (cache->slots) __builtin_prefetch(&cache->slots[cache->head], 0, 3);` + - ※ ただしロードが増えるので、まずは 1. の最小で A/B + +3. **ドキュメント** + - `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=0` vs `=1` + - **GO**: +1.0% 以上 + - **NO-GO**: -1.0% 以下 → freeze + - ±1% は “研究箱維持”(デフォルトOFFのまま) + +## 期待値の現実 + +prefetch は “刺さるときだけ刺さる”。 +勝ち筋は「route 形の整理(B3/B4/C3)で instruction が減った結果、メモリ待ちが相対的に目立つ」状態になっていること。 +もし勝てないなら、次は C2(metadata locality)へ進む。 + diff --git a/docs/analysis/PHASE3_CACHE_LOCALITY_NEXT_INSTRUCTIONS.md b/docs/analysis/PHASE3_CACHE_LOCALITY_NEXT_INSTRUCTIONS.md index 45350ff8..a8b1343a 100644 --- a/docs/analysis/PHASE3_CACHE_LOCALITY_NEXT_INSTRUCTIONS.md +++ b/docs/analysis/PHASE3_CACHE_LOCALITY_NEXT_INSTRUCTIONS.md @@ -49,11 +49,14 @@ ### C1(優先度: 🟡 中): TLS Cache Prefetch -**狙い**: policy_snapshot 実行前に g_small_policy_v7 をプリフェッチ +**狙い**: policy ではなく、実際に alloc が触る **TLS cache**(Unified Cache)をプリフェッチ + +**設計メモ**: `docs/analysis/PHASE3_C1_TLS_PREFETCH_1_DESIGN.md` **実装**: ```c -__builtin_prefetch(g_small_policy_v7, 0, 3); // read intent (prefetch for load) +// malloc_tiny_fast_for_class() 内で、LEGACY route のときだけ: +__builtin_prefetch(&g_unified_cache[class_idx], 0, 3); ``` **期待**: +2-4% diff --git a/docs/specs/ENV_VARS_COMPLETE.md b/docs/specs/ENV_VARS_COMPLETE.md index a81b89b1..0b400853 100644 --- a/docs/specs/ENV_VARS_COMPLETE.md +++ b/docs/specs/ENV_VARS_COMPLETE.md @@ -96,6 +96,12 @@ From `/mnt/workdisk/public_share/hakmem/core/hakmem_tiny_stats.h`: - **Impact**: A/B gate for policy snapshot cost removal (research box until GO) - **Notes**: v7 learner が有効な場合(`HAKMEM_SMALL_HEAP_V7_ENABLED=1` かつ learner 無効化なし)は安全のため強制 OFF +#### HAKMEM_TINY_PREFETCH +- **Default**: 0 (disabled) +- **Purpose**: Prefetch hints for Tiny hot paths (Phase 3 C1) +- **Impact**: `malloc_tiny_fast_for_class()` の LEGACY route で TLS Unified Cache を `__builtin_prefetch()` する A/B gate +- **Notes**: Prefetch は workload 依存。NO-GO なら即 freeze(default OFF のまま) + --- ### 2. Tiny Pool TLS Caching (Performance Critical)