Files
hakmem/docs/analysis/MID_V35_HOTPATH_OPT_1_DESIGN.md

205 lines
7.6 KiB
Markdown
Raw Normal View History

# 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 へ進むか判断