205 lines
7.6 KiB
Markdown
205 lines
7.6 KiB
Markdown
|
|
# 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 へ進むか判断
|