2025-12-12 04:36:37 +09:00
|
|
|
|
# V7 Architecture Decision Matrix
|
|
|
|
|
|
|
|
|
|
|
|
**Date**: 2025-12-12
|
|
|
|
|
|
**Purpose**: mimalloc 競争力評価 + v7-5 方向性の決定基準を明確化
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. mimalloc vs HAKMEM v7 比較表
|
|
|
|
|
|
|
|
|
|
|
|
### 1-1. アーキテクチャ比較
|
|
|
|
|
|
|
|
|
|
|
|
| 要素 | mimalloc | HAKMEM v7 (C6-only) | Gap | 対策 |
|
|
|
|
|
|
|------|----------|---------------------|-----|------|
|
|
|
|
|
|
| **Free List 構造** | Intrusive LIFO (ブロック内 next ptr) | Page metadata explicit freelist | **-2~3%** | Intrusive LIFO 採用検討 |
|
|
|
|
|
|
| **Size Class 数** | 128 (fine-grained) | 8 (C0-C7) | **-1~2%** | 現状維持 (overhead 分摊で対応) |
|
|
|
|
|
|
| **Page Size** | 8KB (L1 cache fit) | 64KB (ULTRA 互換) | **±0%** | tradeoff 異なる (検証必要) |
|
|
|
|
|
|
| **Segment Size** | 4MB on-demand | 2MB fixed | **±0%** | 同等 |
|
|
|
|
|
|
| **Lookup Cost** | Direct array O(1) | RegionIdBox binary search O(log N) | **-1~2%** | TLS fast path で緩和済み |
|
|
|
|
|
|
| **Header** | なし (headerless) | 薄く残す (1 byte) | **-0.5%** | v6 headerless パターン適用検討 |
|
|
|
|
|
|
| **TLS Access** | 1 read + array index | TLS bounds check + page_meta | **-1%** | TLS hint 最適化済み |
|
|
|
|
|
|
| **Remote Free** | Lock-free MPSC | Lock-free MPSC (同等) | **±0%** | 同等 |
|
|
|
|
|
|
| **Stats Overhead** | Batched/deferred | Atomic increment on hot path | **-0.5~1%** | Stats を cold path へ移動 |
|
|
|
|
|
|
|
|
|
|
|
|
### 1-2. Hot Path 比較 (14 ns vs 現状)
|
|
|
|
|
|
|
|
|
|
|
|
**mimalloc hot path** (14 ns):
|
|
|
|
|
|
```c
|
|
|
|
|
|
mi_heap_t* heap = mi_get_default_heap(); // 2 ns: TLS read
|
|
|
|
|
|
int cls = mi_size_to_class(size); // 3 ns: LUT + BSR
|
|
|
|
|
|
mi_page_t* page = heap->pages[cls]; // 1 ns: array index
|
|
|
|
|
|
void* p = page->free; // 3 ns: load free head
|
|
|
|
|
|
page->free = *(void**)p; // 3 ns: update free
|
|
|
|
|
|
return p; // 2 ns
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**HAKMEM v7 hot path** (推定 18-22 ns):
|
|
|
|
|
|
```c
|
|
|
|
|
|
SmallHeapCtx_v7* ctx = small_heap_ctx_v7(); // 2 ns: TLS read
|
|
|
|
|
|
SmallClassHeap_v7* h = &ctx->cls[class_idx]; // 1 ns: array index
|
|
|
|
|
|
SmallPageMeta_v7* p = h->current; // 2 ns: load current
|
|
|
|
|
|
void* base = p->free_list; // 3 ns: load free head
|
|
|
|
|
|
p->free_list = *(void**)base; // 3 ns: update free
|
|
|
|
|
|
p->used++; // 1 ns: counter
|
|
|
|
|
|
((uint8_t*)base)[0] = HEADER_MAGIC | class; // 2 ns: header write
|
|
|
|
|
|
small_v7_stat_alloc(); // 2 ns: atomic stats
|
|
|
|
|
|
return (uint8_t*)base + 1; // 2 ns: USER ptr
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Gap 内訳**:
|
|
|
|
|
|
| Step | mimalloc | v7 | Diff | 削減可能? |
|
|
|
|
|
|
|------|----------|-----|------|----------|
|
|
|
|
|
|
| TLS access | 2 ns | 2 ns | 0 | - |
|
|
|
|
|
|
| Class lookup | 3 ns | 1 ns | -2 ns | ✅ v7 の方が速い |
|
|
|
|
|
|
| Page lookup | 1 ns | 2 ns | +1 ns | 改善可能 |
|
|
|
|
|
|
| Free list op | 6 ns | 6 ns | 0 | - |
|
|
|
|
|
|
| Counter update | 0 ns | 1 ns | +1 ns | cold path へ移動 |
|
|
|
|
|
|
| Header write | 0 ns | 2 ns | +2 ns | headerless 化 |
|
|
|
|
|
|
| Stats | 0 ns | 2 ns | +2 ns | cold path へ移動 |
|
|
|
|
|
|
| Return | 2 ns | 2 ns | 0 | - |
|
|
|
|
|
|
| **Total** | **14 ns** | **18 ns** | **+4 ns** | **-3~4 ns 可能** |
|
|
|
|
|
|
|
|
|
|
|
|
### 1-3. 競争力評価
|
|
|
|
|
|
|
|
|
|
|
|
**現状 v7 の立ち位置**:
|
|
|
|
|
|
- Legacy baseline: 58.6M ops/s
|
|
|
|
|
|
- v7 Phase v7-3: 56.3M ops/s (-4.3%)
|
|
|
|
|
|
- mimalloc 推定: 71M ops/s (+21% vs legacy)
|
|
|
|
|
|
|
|
|
|
|
|
**v7 が mimalloc に追いつくには**:
|
|
|
|
|
|
1. Header write 削除: +2 ns 改善
|
|
|
|
|
|
2. Stats を cold path へ: +2 ns 改善
|
|
|
|
|
|
3. Counter を cold path へ: +1 ns 改善
|
|
|
|
|
|
4. **合計**: 18 ns → 13-14 ns (mimalloc と同等)
|
|
|
|
|
|
|
|
|
|
|
|
**結論**: 設計上 mimalloc と **同等まで到達可能**。ただし intrusive LIFO 採用が鍵。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. v7-5 方向性の決定基準
|
|
|
|
|
|
|
2025-12-12 06:09:12 +09:00
|
|
|
|
### 2-1. v7-5a vs v7-5b 比較表(実績付き)
|
2025-12-12 04:36:37 +09:00
|
|
|
|
|
|
|
|
|
|
| 項目 | v7-5a (C6 極限最適化) | v7-5b (Multi-class 拡張) |
|
|
|
|
|
|
|------|----------------------|-------------------------|
|
|
|
|
|
|
| **目標** | C6-only で -4.3% → ±0% | C5+C6 で overhead 分摊 |
|
|
|
|
|
|
| **作業量** | 小 (hotbox 微調整) | 中 (Segment 複数化, TLS hint 拡張) |
|
|
|
|
|
|
| **リスク** | 効果薄い可能性 (diminishing returns) | 複雑度増加 |
|
|
|
|
|
|
| **成功時の効果** | C6 で mimalloc 同等 | C5+C6 で -2% (予測) |
|
|
|
|
|
|
| **失敗時の影響** | 時間の無駄 (1-2日) | 設計変更のコスト (数日) |
|
|
|
|
|
|
| **検証方法** | A/B bench (C6-heavy) | Mixed bench + per-class stats |
|
|
|
|
|
|
|
|
|
|
|
|
### 2-2. 決定フレームワーク
|
|
|
|
|
|
|
|
|
|
|
|
**v7-5a を選ぶ条件**:
|
|
|
|
|
|
1. C6 の hot path に明確なボトルネックがある
|
|
|
|
|
|
2. Header write / Stats を cold path へ移動する具体策がある
|
|
|
|
|
|
3. 1-2 日で A/B 検証可能
|
|
|
|
|
|
|
|
|
|
|
|
**v7-5b を選ぶ条件**:
|
|
|
|
|
|
1. C6-only では overhead 削減に限界がある (既に TLS 最適化済み)
|
|
|
|
|
|
2. C5/C4 の allocation が実 workload で significant
|
|
|
|
|
|
3. overhead 分摊の理論値 (-4.3% → -2%) が魅力的
|
|
|
|
|
|
|
2025-12-12 06:09:12 +09:00
|
|
|
|
### 2-3. 実績: v7-5a 完了(C6 v7 Hot path stats 削除)
|
2025-12-12 04:36:37 +09:00
|
|
|
|
|
|
|
|
|
|
**理由**:
|
|
|
|
|
|
1. **低コスト**: 1-2 日で結果が出る
|
|
|
|
|
|
2. **具体的改善点が明確**: Header write + Stats 移動
|
|
|
|
|
|
3. **失敗しても学び**: 限界が分かれば v7-5b へ移行
|
|
|
|
|
|
4. **成功すれば**: C6 で mimalloc 同等 → 強力な武器
|
|
|
|
|
|
|
2025-12-12 06:09:12 +09:00
|
|
|
|
**実装内容 (Phase v7-5a, 完了済み)**:
|
|
|
|
|
|
1. C6 v7 Hot path から per-page stats 更新を削除。
|
|
|
|
|
|
- `alloc_count++ / free_count++ / live_current++/--` を ColdIface 経路(refill/retire 時)に移動。
|
|
|
|
|
|
- Hot path での stats は `HAKMEM_V7_HOT_STATS=1` のときだけ ENV ゲートで有効(デフォルト OFF)。
|
|
|
|
|
|
2. Header-at-carve-time の完全移行は見送り。
|
|
|
|
|
|
- freelist が block[0] を next pointer として使っており、「carve 時だけ header write」は v7 現行構造では安全にできないため、ヘッダは引き続き alloc 時に 1 byte 書く前提を維持。
|
|
|
|
|
|
|
|
|
|
|
|
**A/B 結果 (C6-heavy)**:
|
|
|
|
|
|
|
|
|
|
|
|
| Metric | v7 OFF (MID v3) | v7 ON (v7-5a) |
|
|
|
|
|
|
|---------|-----------------|---------------|
|
|
|
|
|
|
| Throughput (avg) | 9.26M ops/s | 9.27M ops/s |
|
|
|
|
|
|
| Delta | baseline | +0.15% |
|
|
|
|
|
|
|
|
|
|
|
|
→ 目標だった `-4.3% → ±2%` を達成し、C6-only v7 は MID v3 とほぼ同等(±0%)になった。
|
|
|
|
|
|
|
|
|
|
|
|
**次の判断軸**:
|
|
|
|
|
|
- v7-5b(Multi-class 拡張)に進むかどうかは、「C5/C4 を v7 に載せて overhead を分摊する価値があるか」の評価次第。
|
|
|
|
|
|
- Intrusive LIFO / headerless / Stats cold path などは v7-5a の結果を踏まえて、別フェーズで改めて検討する。
|
|
|
|
|
|
|
|
|
|
|
|
### 2-4. 実績: v7-5b 完了(C5+C6 multi-class 拡張)
|
|
|
|
|
|
|
|
|
|
|
|
**実装内容 (Phase v7-5b, 完了済み)**:
|
|
|
|
|
|
- SmallSegment_v7 / SmallObjectColdIface_v7 / SmallObjectHotBox_v7 を C5+C6 の 2 クラス対応に拡張。
|
|
|
|
|
|
- `SMALL_V7_CLASS_SUPPORTED()` に C5 を追加。
|
|
|
|
|
|
- `small_v7_block_size()` を C5/C6 両クラスを扱う switch に拡張。
|
|
|
|
|
|
- HotBox 側の alloc/free class validation を C5+C6 対応に更新。
|
|
|
|
|
|
- TLS 構造は C6 lane を維持しつつ、C5 については v7 small コアに乗せるが、C6 TLS のキャッシュ線を肥大化させない形をキープ。
|
|
|
|
|
|
|
|
|
|
|
|
**A/B 結果 (C5+C6 v7 プロファイル)**:
|
|
|
|
|
|
|
|
|
|
|
|
| Config | Avg Throughput | Delta |
|
|
|
|
|
|
|------------|----------------|----------|
|
|
|
|
|
|
| C6-only v7 | 7.64M ops/s | baseline |
|
|
|
|
|
|
| C5+C6 v7 | 7.97M ops/s | +4.3% |
|
|
|
|
|
|
|
|
|
|
|
|
- C6 性能維持: ✅(C6-only v7 と比べて劣化なし)
|
|
|
|
|
|
- C5 net positive: ✅(+4.3%)
|
|
|
|
|
|
- TLS bloat: ✅ なし(C6 TLS lane のヒット率に悪影響なし)
|
|
|
|
|
|
|
|
|
|
|
|
**今後の方向性**:
|
|
|
|
|
|
- C4 は現在 ULTRA 本線で十分速いため、v7 に載せるかどうかは別途慎重に判断(Phase v7-5c 候補)。
|
|
|
|
|
|
- v7 small/mid コアは C5+C6 2 クラス対応でも破綻しないことが分かったので、次は Mixed 16–1024B の A/B や Learner 連携(動的 route 選択)の設計・検証に進む。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. C5 ルート選択と Learner 連携の必要性
|
|
|
|
|
|
|
|
|
|
|
|
Mixed / C5+C6 専用での A/B から、C5 v7 の利得が workload-dependent であることが判明した:
|
|
|
|
|
|
|
|
|
|
|
|
| Workload | C6-only v7 | C5+C6 v7 | 推奨設定 |
|
|
|
|
|
|
|----------------------|------------|----------|----------------|
|
|
|
|
|
|
| C5+C6 専用 (257–768B) | baseline | +4.3% | `CLASSES=0x60` |
|
|
|
|
|
|
| Mixed 16–1024B | +0.5% | -8.0% | `CLASSES=0x40` |
|
|
|
|
|
|
|
|
|
|
|
|
結論:
|
|
|
|
|
|
- C5 は C5-heavy な専用 workload では v7 が有利だが、一般的な Mixed では MID v3+ULTRA の方が全体として速い。
|
|
|
|
|
|
- 「ENV で C5 を常に v7 にする / 常に MID v3 にする」ような固定方針は現実的でなく、**Learner で C5 の route を動的に切り替える設計**が必要。
|
2025-12-12 04:36:37 +09:00
|
|
|
|
|
2025-12-12 06:09:12 +09:00
|
|
|
|
設計メモ(v7-7 以降):
|
|
|
|
|
|
- Stats → Learner → Policy route_kind 更新の最小パス:
|
|
|
|
|
|
- `SmallPageStatsV7`(ColdIface で retire 時に生成)
|
|
|
|
|
|
→ `SmallLearnerStatsV7`(per-class 累積 alloc/free/remote)
|
|
|
|
|
|
→ PolicyLearner(C5 alloc 比率が閾値を超えているか判定)
|
|
|
|
|
|
→ `SmallPolicyV7.route_kind[C5]` を `SMALL_ROUTE_V7` or `SMALL_ROUTE_MID_V3` に更新。
|
|
|
|
|
|
- 最初の版では C5 だけを対象とし、他クラス(C4/C6 など)の動的ルート選択は後続フェーズで検討する。
|
2025-12-12 04:36:37 +09:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. Intrusive LIFO 採用検討
|
|
|
|
|
|
|
|
|
|
|
|
### 3-1. 現状 (Explicit Freelist)
|
|
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
|
// SmallPageMeta_v7
|
|
|
|
|
|
void* free_list; // page metadata に freelist head
|
|
|
|
|
|
|
|
|
|
|
|
// Alloc
|
|
|
|
|
|
void* base = p->free_list;
|
|
|
|
|
|
p->free_list = *(void**)base;
|
|
|
|
|
|
|
|
|
|
|
|
// Free
|
|
|
|
|
|
*(void**)base = p->free_list;
|
|
|
|
|
|
p->free_list = base;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**問題**: free_list が page_meta 内にあり、間接参照が必要。
|
|
|
|
|
|
|
|
|
|
|
|
### 3-2. Intrusive LIFO (mimalloc 方式)
|
|
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
|
// Block 内に next pointer を埋め込む
|
|
|
|
|
|
// Free block:
|
|
|
|
|
|
// +0: next_ptr (8 bytes) - 次の free block へのポインタ
|
|
|
|
|
|
// +8: (unused)
|
|
|
|
|
|
|
|
|
|
|
|
// Alloc
|
|
|
|
|
|
void* p = page->free; // free head (block 先頭)
|
|
|
|
|
|
page->free = *(void**)p; // block 内の next を読む
|
|
|
|
|
|
|
|
|
|
|
|
// Free
|
|
|
|
|
|
*(void**)p = page->free; // block 内に next を書く
|
|
|
|
|
|
page->free = p;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**利点**:
|
|
|
|
|
|
- **Zero metadata per block**: free 時に block 自身に next を書く
|
|
|
|
|
|
- **Cache locality**: 直前に free した block は L1 cache にある
|
|
|
|
|
|
- **Minimal indirection**: page→free だけで完結
|
|
|
|
|
|
|
|
|
|
|
|
### 3-3. v7 への適用可能性
|
|
|
|
|
|
|
|
|
|
|
|
**現状 v7 の構造**:
|
|
|
|
|
|
```
|
|
|
|
|
|
SmallPageMeta_v7
|
|
|
|
|
|
├── free_list (void*) ← page_meta 内
|
|
|
|
|
|
├── used (uint32_t)
|
|
|
|
|
|
├── capacity (uint32_t)
|
|
|
|
|
|
└── ...
|
|
|
|
|
|
|
|
|
|
|
|
Block (512B for C6)
|
|
|
|
|
|
├── [0]: header (1 byte) ← USER ptr = base + 1
|
|
|
|
|
|
└── [1-511]: user data
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Intrusive 化案**:
|
|
|
|
|
|
```
|
|
|
|
|
|
SmallPageMeta_v7
|
|
|
|
|
|
├── free (void*) ← 直接 block を指す (base ptr)
|
|
|
|
|
|
├── used (uint32_t)
|
|
|
|
|
|
└── ...
|
|
|
|
|
|
|
|
|
|
|
|
Free Block (512B)
|
|
|
|
|
|
├── [0-7]: next_ptr ← intrusive next pointer
|
|
|
|
|
|
└── [8-511]: (unused when free)
|
|
|
|
|
|
|
|
|
|
|
|
Allocated Block (512B)
|
|
|
|
|
|
├── [0]: header (optional)
|
|
|
|
|
|
└── [1-511]: user data
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**変更点**:
|
|
|
|
|
|
1. `free_list` を `free` にリネーム (semantic 変更)
|
|
|
|
|
|
2. free 時: `*(void**)base = page->free; page->free = base;`
|
|
|
|
|
|
3. alloc 時: `void* p = page->free; page->free = *(void**)p;`
|
|
|
|
|
|
4. Header は USER ptr 計算時のみ使用 (hot path から削除可能)
|
|
|
|
|
|
|
|
|
|
|
|
### 3-4. 採用判断
|
|
|
|
|
|
|
|
|
|
|
|
**採用する場合のメリット**:
|
|
|
|
|
|
- +2 ns 改善 (page_meta 間接参照削減)
|
|
|
|
|
|
- mimalloc と同じデータ構造 → 同等性能の可能性
|
|
|
|
|
|
|
|
|
|
|
|
**採用しない場合の理由**:
|
|
|
|
|
|
- 既存 v7 コードの変更が必要
|
|
|
|
|
|
- Header との互換性を慎重に検討必要
|
|
|
|
|
|
- v6 headerless との設計統合を先に検討すべき
|
|
|
|
|
|
|
|
|
|
|
|
**結論**: **v7-5a の後で検討**。まず Header/Stats 削除で効果を測る。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. TLS Cache Hit Rate 目標
|
|
|
|
|
|
|
|
|
|
|
|
### 4-1. 現状の TLS Fast Path
|
|
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
|
// Phase v7-3 で追加
|
|
|
|
|
|
if (addr >= ctx->tls_seg_base && addr < ctx->tls_seg_end) {
|
|
|
|
|
|
// TLS hit: RegionIdBox skip
|
|
|
|
|
|
size_t page_idx = (addr - ctx->tls_seg_base) >> SMALL_PAGE_V7_SHIFT;
|
|
|
|
|
|
SmallPageMeta_v7* page = &seg->page_meta[page_idx];
|
|
|
|
|
|
// ... free logic
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// TLS miss: RegionIdBox fallback
|
|
|
|
|
|
RegionLookupV6 lk = region_id_lookup_v6(ptr);
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4-2. Hit Rate 目標
|
|
|
|
|
|
|
|
|
|
|
|
| Workload | TLS Hit Rate 目標 | 現状推定 | 根拠 |
|
|
|
|
|
|
|----------|------------------|----------|------|
|
|
|
|
|
|
| C6-heavy | 99%+ | 95-98% | ほぼ同一 segment |
|
|
|
|
|
|
| Mixed | 90%+ | 80-90% | 複数 class で分散 |
|
|
|
|
|
|
| Multi-thread | 85%+ | 75-85% | Remote free 混在 |
|
|
|
|
|
|
|
|
|
|
|
|
### 4-3. Hit Rate 測定方法
|
|
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
|
// ENV: HAKMEM_V7_TLS_STATS=1
|
|
|
|
|
|
static uint64_t g_v7_tls_hit = 0;
|
|
|
|
|
|
static uint64_t g_v7_tls_miss = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// In free path
|
|
|
|
|
|
if (addr >= ctx->tls_seg_base && addr < ctx->tls_seg_end) {
|
|
|
|
|
|
__sync_fetch_and_add(&g_v7_tls_hit, 1);
|
|
|
|
|
|
// ...
|
|
|
|
|
|
} else {
|
|
|
|
|
|
__sync_fetch_and_add(&g_v7_tls_miss, 1);
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// At exit
|
|
|
|
|
|
fprintf(stderr, "[V7_TLS] hit=%lu miss=%lu rate=%.2f%%\n",
|
|
|
|
|
|
g_v7_tls_hit, g_v7_tls_miss,
|
|
|
|
|
|
100.0 * g_v7_tls_hit / (g_v7_tls_hit + g_v7_tls_miss));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4-4. 改善策 (Hit Rate < 目標の場合)
|
|
|
|
|
|
|
|
|
|
|
|
1. **Multi-segment TLS hint** (v7-5b で必要):
|
|
|
|
|
|
```c
|
|
|
|
|
|
struct {
|
|
|
|
|
|
uintptr_t seg_base;
|
|
|
|
|
|
uintptr_t seg_end;
|
|
|
|
|
|
SmallSegment_v7* seg;
|
|
|
|
|
|
} tls_seg[5]; // C3-C7 用
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **Last-page cache** (既に設計あり):
|
|
|
|
|
|
```c
|
|
|
|
|
|
uintptr_t last_page_base;
|
|
|
|
|
|
uintptr_t last_page_end;
|
|
|
|
|
|
SmallPageMeta_v7* last_page_meta;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **Segment 再利用**: 同一 class の allocation が同一 segment に集中するよう誘導
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Overhead 内訳の実測計画
|
|
|
|
|
|
|
|
|
|
|
|
### 5-1. 現状の仮説 (-4.3% 内訳)
|
|
|
|
|
|
|
|
|
|
|
|
| 要因 | 推定 | 対策 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| Page metadata 間接参照 | ~2% | Intrusive LIFO |
|
|
|
|
|
|
| Extra validation | ~1% | Branch 最適化 |
|
|
|
|
|
|
| RegionIdBox fallback | ~1% | TLS cache 強化 |
|
|
|
|
|
|
| Header write | ~0.3% | Headerless 化 |
|
|
|
|
|
|
| **合計** | **~4.3%** | |
|
|
|
|
|
|
|
|
|
|
|
|
### 5-2. 実測方法
|
|
|
|
|
|
|
|
|
|
|
|
**Step 1: Header write 削除**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# ENV で headerless 有効化
|
|
|
|
|
|
HAKMEM_V7_HEADERLESS=1 ./bench_random_mixed_hakmem
|
|
|
|
|
|
# 効果測定: -0.3% 改善なら仮説検証
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Step 2: Stats 削除**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Stats を compile-time で無効化
|
|
|
|
|
|
make clean && make CFLAGS="-DHAKMEM_V7_NO_STATS"
|
|
|
|
|
|
# 効果測定: -0.5% 改善なら仮説検証
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Step 3: TLS hit rate 測定**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
HAKMEM_V7_TLS_STATS=1 ./bench_random_mixed_hakmem
|
|
|
|
|
|
# Hit rate < 90% なら TLS 改善が必要
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Step 4: Page metadata 間接参照**
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Intrusive LIFO 試験実装
|
|
|
|
|
|
# 効果測定: -2% 改善なら大きな勝利
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5-3. 検証完了基準
|
|
|
|
|
|
|
|
|
|
|
|
| 仮説 | 実測結果 | 判定 |
|
|
|
|
|
|
|------|----------|------|
|
|
|
|
|
|
| Header write ~0.3% | 実測値 | ±0.2% なら OK |
|
|
|
|
|
|
| Stats ~0.5% | 実測値 | ±0.3% なら OK |
|
|
|
|
|
|
| TLS fallback ~1% | Hit rate × miss cost | 計算で検証 |
|
|
|
|
|
|
| Page metadata ~2% | Intrusive 後の差分 | ±0.5% なら OK |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 次のアクション
|
|
|
|
|
|
|
|
|
|
|
|
### 6-1. 即時 (v7-5a: 1-2 日)
|
|
|
|
|
|
|
|
|
|
|
|
1. **Header write 条件化**:
|
|
|
|
|
|
- `smallobject_hotbox_v7_box.h` に `#ifdef HAKMEM_V7_HEADERLESS` 追加
|
|
|
|
|
|
- Free path で header validation をスキップ
|
|
|
|
|
|
|
|
|
|
|
|
2. **Stats を cold path へ**:
|
|
|
|
|
|
- `small_v7_stat_alloc()` を `#ifdef HAKMEM_V7_STATS` で囲む
|
|
|
|
|
|
- Default OFF で bench
|
|
|
|
|
|
|
|
|
|
|
|
3. **A/B bench**:
|
|
|
|
|
|
- C6-heavy: `HAKMEM_BENCH_MIN_SIZE=400 HAKMEM_BENCH_MAX_SIZE=510`
|
|
|
|
|
|
- v7 ON/OFF 比較
|
|
|
|
|
|
|
|
|
|
|
|
### 6-2. 短期 (v7-5a 評価後: 2-3 日)
|
|
|
|
|
|
|
|
|
|
|
|
4. **TLS hit rate 測定**:
|
|
|
|
|
|
- Stats 追加して hit/miss ratio 確認
|
|
|
|
|
|
- < 90% なら multi-segment hint 検討
|
|
|
|
|
|
|
|
|
|
|
|
5. **Intrusive LIFO 試験**:
|
|
|
|
|
|
- small_heap_alloc_fast_v7 を intrusive 版に書き換え
|
|
|
|
|
|
- A/B bench で効果測定
|
|
|
|
|
|
|
|
|
|
|
|
### 6-3. 中期 (v7-5b 検討: 1 週間)
|
|
|
|
|
|
|
|
|
|
|
|
6. **Multi-class 拡張設計**:
|
|
|
|
|
|
- C5 対応の Segment 設計
|
|
|
|
|
|
- TLS context 拡張 (tls_seg[5])
|
|
|
|
|
|
|
|
|
|
|
|
7. **v6 headerless 統合**:
|
|
|
|
|
|
- v6 と v7 の headerless パターン統合
|
|
|
|
|
|
- RegionIdBox で class_idx 取得を共通化
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 結論
|
|
|
|
|
|
|
|
|
|
|
|
### mimalloc に勝てるか?
|
|
|
|
|
|
|
|
|
|
|
|
**Yes, 設計上は可能**。
|
|
|
|
|
|
|
|
|
|
|
|
条件:
|
|
|
|
|
|
1. Intrusive LIFO 採用 (+2 ns)
|
|
|
|
|
|
2. Header write 削除 (+2 ns)
|
|
|
|
|
|
3. Stats を cold path へ (+2 ns)
|
|
|
|
|
|
4. TLS hit rate 90%+ 維持
|
|
|
|
|
|
|
|
|
|
|
|
これで v7 は 13-14 ns (mimalloc 同等) に到達可能。
|
|
|
|
|
|
|
|
|
|
|
|
### v7-5 の推奨
|
|
|
|
|
|
|
|
|
|
|
|
**v7-5a (C6 極限最適化) を先に実施**。
|
|
|
|
|
|
|
|
|
|
|
|
理由:
|
|
|
|
|
|
- 低コスト (1-2 日)
|
|
|
|
|
|
- 具体的改善点が明確
|
|
|
|
|
|
- 成功すれば v7-5b は不要かもしれない
|
|
|
|
|
|
- 失敗しても学びがある
|
|
|
|
|
|
|
|
|
|
|
|
### 最終目標
|
|
|
|
|
|
|
|
|
|
|
|
| Phase | 目標 | 達成基準 |
|
|
|
|
|
|
|-------|------|----------|
|
|
|
|
|
|
| v7-5a | C6 で legacy ±2% | C6-heavy bench |
|
|
|
|
|
|
| v7-5b | C5+C6 で legacy ±0% | Mixed bench |
|
|
|
|
|
|
| v7-6 | mimalloc 同等 | Intrusive LIFO + Headerless |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**Document Status**: COMPLETE
|
|
|
|
|
|
**Next Action**: v7-5a 実装開始
|
|
|
|
|
|
**Decision Owner**: User
|