# Phase MID-V35-HOTPATH-OPT-1-DESIGN ## 目的 Mixed本線(MIXED_TINYV3_C7_SAFE)の alloc側最大ホット(MID v3.5 / C5-C6パス)を最適化する。 **背景**: - Phase POLICY-FAST-PATH-V2 で free 側ホットは崩せなかった(大WS時の分岐コスト) - perf: `tiny_alloc_gate_fast` が 19-26% を占める(C6-heavy で顕著) - MID v3.5 は C5/C6 で使用され、Mixed 本線のクリティカルパス ## 現状分析 ### `small_mid_v35_alloc()` のホットパス (core/smallobject_mid_v35.c:71-116) ```c void* small_mid_v35_alloc(uint32_t class_idx, size_t size) { (void)size; // ① 未使用パラメータ if (class_idx < 5 || class_idx > 7) return NULL; // ② 境界チェック SmallMidV35TlsCtx *ctx = &tls_mid_v35_ctx; // Fast path if (ctx->page[class_idx] && ctx->offset[class_idx] < ctx->capacity[class_idx]) { size_t slot_size = g_slot_sizes[class_idx]; // ③ 配列参照 void *base = (char*)ctx->page[class_idx] + ctx->offset[class_idx] * slot_size; ctx->offset[class_idx]++; // ④ Stats更新(必須ではない) if (ctx->meta[class_idx]) { ctx->meta[class_idx]->alloc_count++; } // ⑤ ヘッダー書き込み tiny_region_id_write_header(base, class_idx); return (char*)base + 1; } // Slow path: ColdIface refill ... } ``` ### 削減可能な work | # | 箇所 | 現状 | 最適化案 | 期待効果 | |---|------|------|---------|---------| | ① | `(void)size` | 毎回渡される | size パラメータ削除 | 微小 | | ② | 境界チェック | 毎回 | caller 側で保証、ここでは削除 | ~1-2 cycles | | ③ | `g_slot_sizes[class_idx]` | 配列参照 | TLS ctx に slot_size を持たせる | ~1-2 cycles | | ④ | `alloc_count++` | 毎回 | ENV gate で disable 可能に | ~2-3 cycles | | ⑤ | ヘッダー書き込み | 毎回必須 | 最適化不可(必須) | - | ### `small_mid_v35_free()` のホットパス (core/smallobject_mid_v35.c:123-160) ```c void small_mid_v35_free(void *ptr, uint32_t class_idx) { if (!ptr || class_idx < 5 || class_idx > 7) return; // ① 境界チェック void *base = (char*)ptr - 1; // ② page_base 計算(毎回) size_t page_size = 64 * 1024; void *page_base = (void*)((uintptr_t)base & ~(page_size - 1)); SmallMidV35TlsCtx *ctx = &tls_mid_v35_ctx; SmallPageMeta_MID_v3 *meta = ctx->meta[class_idx]; if (meta && meta->ptr == page_base) { // ③ Stats更新 meta->free_count++; // ④ Retire チェック if (meta->free_count >= meta->capacity) { small_cold_mid_v3_retire_page(meta); ... } } ... } ``` | # | 箇所 | 現状 | 最適化案 | 期待効果 | |---|------|------|---------|---------| | ① | 境界チェック | 毎回 | caller 側で保証 | ~1-2 cycles | | ② | page_base 計算 | `& ~(64K-1)` | TLS ctx に page_base を持たせる | ~2-3 cycles | | ③ | `free_count++` | 毎回 | ENV gate で disable 可能に | ~2-3 cycles | | ④ | retire チェック | 毎回分岐 | N 回に1回だけチェック (batch retire) | ~1-2 cycles avg | ## 箱化計画 ### Box 1: Stats Gate (削減優先度: 高) **新規ファイル**: `core/box/mid_v35_stats_gate_box.h` ```c // ENV: HAKMEM_MID_V35_STATS_ENABLED (default 1) static inline bool mid_v35_stats_enabled(void) { static int g_enabled = -1; if (__builtin_expect(g_enabled == -1, 0)) { const char* e = getenv("HAKMEM_MID_V35_STATS_ENABLED"); g_enabled = (e && *e == '0') ? 0 : 1; // default ON for compatibility } return g_enabled; } #define MID_V35_STAT_INC(field) \ do { if (__builtin_expect(mid_v35_stats_enabled(), 1)) { (field)++; } } while(0) ``` **適用箇所**: - `ctx->meta[class_idx]->alloc_count++` → `MID_V35_STAT_INC(ctx->meta[class_idx]->alloc_count)` - `meta->free_count++` → `MID_V35_STAT_INC(meta->free_count)` **戻しノブ**: `HAKMEM_MID_V35_STATS_ENABLED=0` で stats 無効化 ### Box 2: TLS Layout Optimization (削減優先度: 中) **変更ファイル**: `core/smallobject_mid_v35.c` ```c typedef struct { void *page[8]; uint32_t offset[8]; uint32_t capacity[8]; SmallPageMeta_MID_v3 *meta[8]; // 追加フィールド size_t slot_size[8]; // キャッシュ済み slot size void *page_base[8]; // キャッシュ済み page base (for free comparison) } SmallMidV35TlsCtx; ``` **効果**: - `g_slot_sizes[class_idx]` 配列参照を TLS 読み出しに変更(キャッシュヒット改善) - `page_base` 計算を refill 時の1回だけに削減 ### Box 3: Boundary Check Elimination (削減優先度: 低) **変更ファイル**: `core/front/malloc_tiny_fast.h` caller 側で `class_idx >= 5 && class_idx <= 7` を保証し、`small_mid_v35_alloc/free` 内のチェックを削除。 **リスク**: 誤った class_idx で呼ばれた場合のクラッシュ(DEBUG ビルドでは assert 追加) ## 境界定義 ``` ┌─────────────────────────────────────────────────────────────┐ │ malloc_tiny_fast.h │ │ (caller: class_idx 保証、ルーティング決定) │ ├─────────────────────────────────────────────────────────────┤ │ smallobject_mid_v35.c │ │ L1 HotBox: TLS fast path (alloc/free) │ │ - Stats Gate (Box 1) で stats 更新を条件付きに │ │ - TLS Layout (Box 2) で配列参照/計算を削減 │ ├─────────────────────────────────────────────────────────────┤ │ smallobject_cold_iface_mid_v3.c │ │ L2 ColdIface: refill/retire (変更なし) │ └─────────────────────────────────────────────────────────────┘ ``` ## 戻しノブ一覧 | ENV | Default | 説明 | |-----|---------|------| | `HAKMEM_MID_V35_STATS_ENABLED` | 1 (ON) | 0 で stats 更新を無効化 | | `HAKMEM_MID_V35_FAST_TLS` | 0 (OFF) | 1 で TLS layout 最適化を有効化 | ## 実装順序 1. **Phase 1 (Box 1)**: Stats Gate 追加 - `mid_v35_stats_gate_box.h` 作成 - `smallobject_mid_v35.c` に適用 - A/B: `HAKMEM_MID_V35_STATS_ENABLED=0` vs `=1` - 期待: +2-5% (stats overhead 削除分) 2. **Phase 2 (Box 2)**: TLS Layout 最適化 - `SmallMidV35TlsCtx` 拡張 - refill 時に slot_size/page_base をキャッシュ - A/B: `HAKMEM_MID_V35_FAST_TLS=1` vs `=0` - 期待: +1-3% (配列参照/計算削減分) 3. **Phase 3 (Box 3)**: Boundary Check 削除 (optional) - DEBUG assert のみ残す - Release ビルドで無条件削除 - 期待: +0.5-1% ## 期待効果まとめ | Box | 対象 | 期待効果 | リスク | |-----|------|---------|--------| | Box 1 | Stats Gate | +2-5% | 低 (stats 無効は研究用) | | Box 2 | TLS Layout | +1-3% | 低 (TLS サイズ増) | | Box 3 | Boundary Check | +0.5-1% | 中 (誤 class_idx でクラッシュ) | **合計期待**: +3-9% (Mixed本線) ## 次のアクション 1. この設計 doc をレビュー 2. Phase 1 (Box 1: Stats Gate) を実装 3. A/B テストで効果確認 4. Phase 2, 3 へ進むか判断