270 lines
9.4 KiB
Markdown
270 lines
9.4 KiB
Markdown
|
|
# Phase 6: Front FastLane(Layer Collapse)実装完了レポート
|
|||
|
|
|
|||
|
|
## 実装日時
|
|||
|
|
2025-12-14
|
|||
|
|
|
|||
|
|
## ステータス
|
|||
|
|
**✅ GO** - Mixed 10-run で **+11.13%** の顕著な改善を確認(A/B 実施済み)
|
|||
|
|
|
|||
|
|
参照:
|
|||
|
|
- A/B 結果: `docs/analysis/PHASE6_FRONT_FASTLANE_1_AB_TEST_RESULTS.md`
|
|||
|
|
|
|||
|
|
## 概要
|
|||
|
|
|
|||
|
|
Phase 6 では、malloc/free の入口で発生している「wrapper→gate→policy→route」の固定費を **Hot 側 1 箱** に畳み、**Cold 側へ落ちるのは 1 箇所**(単一フォールバック)にする Layer Collapse 最適化を実装しました。
|
|||
|
|
|
|||
|
|
設計ドキュメント:
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/docs/analysis/PHASE6_FRONT_FASTLANE_1_DESIGN.md`
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/docs/analysis/PHASE6_FRONT_FASTLANE_NEXT_INSTRUCTIONS.md`
|
|||
|
|
|
|||
|
|
## 実装内容
|
|||
|
|
|
|||
|
|
### Patch 1: ENV gate を箱化
|
|||
|
|
|
|||
|
|
**新規ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_env_box.h` (getter)
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_env_box.c` (optional refresh)
|
|||
|
|
|
|||
|
|
**機能:**
|
|||
|
|
- ENV: `HAKMEM_FRONT_FASTLANE=0/1` (default 1, opt-out)
|
|||
|
|
- Optional: `HAKMEM_FRONT_FASTLANE_CLASS_MASK=0x..` (段階導入用, default 0xFF)
|
|||
|
|
- Lazy init (getenv on first call, atomic cache)
|
|||
|
|
- Zero overhead when disabled (static cached)
|
|||
|
|
|
|||
|
|
### Patch 2: FrontFastLaneBox(stub)
|
|||
|
|
|
|||
|
|
**新規ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_box.h` (hot inline / try_* API)
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_box.c` (cold helper / stats)
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_stats_box.h` (stats counters)
|
|||
|
|
|
|||
|
|
**API:**
|
|||
|
|
```c
|
|||
|
|
void* front_fastlane_try_malloc(size_t size) // Success: non-NULL, Fail: NULL
|
|||
|
|
bool front_fastlane_try_free(void* ptr) // Success: true, Fail: false
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Stats (最小):**
|
|||
|
|
- `fastlane_malloc_hit/fallback` (6種類の fallback reason)
|
|||
|
|
- `fastlane_free_hit/fallback` (7種類の fallback reason)
|
|||
|
|
|
|||
|
|
### Patch 3: malloc wrapper に統合(1箇所だけ)
|
|||
|
|
|
|||
|
|
**変更ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/hak_wrappers.inc.h` (lines 179-189)
|
|||
|
|
|
|||
|
|
**統合点:**
|
|||
|
|
- BenchFast の直後、tiny 試行の直前に挿入
|
|||
|
|
- Fail は既存の wrapper 経路に fall-through(境界 1 箇所)
|
|||
|
|
|
|||
|
|
**コード:**
|
|||
|
|
```c
|
|||
|
|
// Phase 6: Front FastLane (Layer Collapse)
|
|||
|
|
if (__builtin_expect(front_fastlane_enabled(), 1)) {
|
|||
|
|
void* p = front_fastlane_try_malloc(size);
|
|||
|
|
if (__builtin_expect(p != NULL, 1)) {
|
|||
|
|
return p; // Success: handled by FastLane
|
|||
|
|
}
|
|||
|
|
// Fallback: not handled, continue to existing wrapper path
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Patch 4: malloc の FastLane 実装(Tiny のみ)
|
|||
|
|
|
|||
|
|
**変更ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_box.h` (lines 50-89)
|
|||
|
|
|
|||
|
|
**実装方針:**
|
|||
|
|
- **既存の勝ち箱を 1 回だけ読む**で構成
|
|||
|
|
- `tiny_get_max_size()`: Cached max size check (typically 256 or 1024)
|
|||
|
|
- `hak_tiny_size_to_class(size)`: Single LUT lookup, no branches
|
|||
|
|
- `front_fastlane_class_mask()`: Gradual rollout support
|
|||
|
|
- `malloc_tiny_fast_for_class(size, class_idx)`: Existing hot handler (no duplication)
|
|||
|
|
|
|||
|
|
**Fail-fast ルール:**
|
|||
|
|
- FastLane 内で **同じ判定を二度しない**(重複排除が主目的)
|
|||
|
|
- 失敗したら即 return NULL(wrapper に戻す)
|
|||
|
|
|
|||
|
|
**Fallback reasons:**
|
|||
|
|
1. `malloc_fallback_size`: Size > tiny_get_max_size()
|
|||
|
|
2. `malloc_fallback_class`: Invalid class_idx (< 0 or >= 8)
|
|||
|
|
3. `malloc_fallback_other`: Class not enabled in mask
|
|||
|
|
4. `malloc_fallback_alloc`: Allocation failed (refill needed)
|
|||
|
|
|
|||
|
|
### Patch 5: free wrapper に統合(1箇所だけ)
|
|||
|
|
|
|||
|
|
**変更ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/hak_wrappers.inc.h` (lines 634-643)
|
|||
|
|
|
|||
|
|
**統合点:**
|
|||
|
|
- `ptr == NULL` の後、heavy classify の前に挿入
|
|||
|
|
|
|||
|
|
**コード:**
|
|||
|
|
```c
|
|||
|
|
// Phase 6: Front FastLane (Layer Collapse) - free path
|
|||
|
|
if (__builtin_expect(front_fastlane_enabled(), 1)) {
|
|||
|
|
if (front_fastlane_try_free(ptr)) {
|
|||
|
|
return; // Success: handled by FastLane
|
|||
|
|
}
|
|||
|
|
// Fallback: not handled, continue to existing wrapper path
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Patch 6: free の FastLane 実装(Tiny 直通のみ)
|
|||
|
|
|
|||
|
|
**変更ファイル:**
|
|||
|
|
- `/mnt/workdisk/public_share/hakmem/core/box/front_fastlane_box.h` (lines 95-153)
|
|||
|
|
|
|||
|
|
**実装方針:**
|
|||
|
|
- E5-1 の header 判定パターン(`HAKMEM_FREE_TINY_DIRECT`)を再利用
|
|||
|
|
- **確信が持てる場合のみ** Tiny free に直行
|
|||
|
|
- それ以外は not-handled (false を返す)
|
|||
|
|
|
|||
|
|
**処理フロー:**
|
|||
|
|
1. Page boundary guard: `(ptr & 0xFFFu) == 0` → fallback (unsafe to read header)
|
|||
|
|
2. Fast header validation: `*((uint8_t*)ptr - 1)`
|
|||
|
|
3. Magic check: `(header & 0xF0u) == 0xA0u` → Tiny header
|
|||
|
|
4. Class extraction: `(header & 0x0Fu)` → class_idx < 8
|
|||
|
|
5. Class mask check: `((mask >> class_idx) & 1)` → enabled
|
|||
|
|
6. Call existing hot handler: `free_tiny_fast(ptr)` → returns 1 on success
|
|||
|
|
|
|||
|
|
**Fallback reasons:**
|
|||
|
|
1. `free_fallback_aligned`: Page-aligned pointer
|
|||
|
|
2. `free_fallback_header`: Invalid header magic
|
|||
|
|
3. `free_fallback_class`: Class out of bounds
|
|||
|
|
4. `free_fallback_failure`: Free failed (cold path needed)
|
|||
|
|
5. `free_fallback_other`: Other reasons (no header support, class not enabled)
|
|||
|
|
|
|||
|
|
## 既存ビルド問題の修正
|
|||
|
|
|
|||
|
|
Phase 6 の実装中に、既存の `g_free_cold_shape` 未定義参照エラーを発見しました。これは Phase 6 とは無関係な既存のビルド問題でした。
|
|||
|
|
|
|||
|
|
**修正内容:**
|
|||
|
|
|
|||
|
|
1. **tiny_header_box.h の修正:**
|
|||
|
|
- `tiny_header_write_once_enabled()` の forward 宣言を削除
|
|||
|
|
- `#include "tiny_header_write_once_env_box.h"` に置き換え
|
|||
|
|
- 理由: extern 宣言と static inline の衝突
|
|||
|
|
|
|||
|
|
2. **Makefile の修正:**
|
|||
|
|
- 以下のオブジェクトファイルを追加:
|
|||
|
|
- `core/box/free_cold_shape_env_box.o`
|
|||
|
|
- `core/box/free_cold_shape_stats_box.o`
|
|||
|
|
- 追加先:
|
|||
|
|
- `OBJS_BASE` (line 221)
|
|||
|
|
- `BENCH_HAKMEM_OBJS_BASE` (line 253)
|
|||
|
|
- `TINY_BENCH_OBJS_BASE` (line 430)
|
|||
|
|
|
|||
|
|
## ビルド結果
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
$ make clean && make bench_random_mixed_hakmem
|
|||
|
|
gcc -o bench_random_mixed_hakmem bench_random_mixed_hakmem.o ... -lm -lpthread -flto
|
|||
|
|
lto-wrapper: warning: using serial compilation of 9 LTRANS jobs
|
|||
|
|
$ ls -lh bench_random_mixed_hakmem
|
|||
|
|
-rwxrwxr-x 1 tomoaki tomoaki 631K 12月 14 09:49 bench_random_mixed_hakmem
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**ビルド成功!**
|
|||
|
|
|
|||
|
|
## 動作確認
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# FastLane OFF
|
|||
|
|
$ HAKMEM_FRONT_FASTLANE=0 ./bench_random_mixed_hakmem 1
|
|||
|
|
[BENCH_FAST] HAKMEM_BENCH_FAST_MODE not set, skipping init
|
|||
|
|
[LIBM_RELOC_GUARD] base=0x7d781a6df000 slot=0x7d781a7c4d88 raw=0x7d781a6ed420 relocated=1
|
|||
|
|
[RSS] max_kb=29184
|
|||
|
|
...
|
|||
|
|
|
|||
|
|
# FastLane ON
|
|||
|
|
$ HAKMEM_FRONT_FASTLANE=1 ./bench_random_mixed_hakmem 1
|
|||
|
|
[BENCH_FAST] HAKMEM_BENCH_FAST_MODE not set, skipping init
|
|||
|
|
[Rel-Unified] unified_cache_enabled() = 1
|
|||
|
|
[POLICY_V7_INIT] Route assignments:
|
|||
|
|
C0: LEGACY, C1: LEGACY, C2: LEGACY, C3: LEGACY, C4: LEGACY, C5: LEGACY
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**両方とも正常に起動!**
|
|||
|
|
|
|||
|
|
## 新規追加ファイル一覧
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
core/box/front_fastlane_env_box.h (ENV gate getter)
|
|||
|
|
core/box/front_fastlane_env_box.c (ENV gate refresh, optional)
|
|||
|
|
core/box/front_fastlane_box.h (Hot inline try_* API)
|
|||
|
|
core/box/front_fastlane_box.c (Cold helper / stats dump)
|
|||
|
|
core/box/front_fastlane_stats_box.h (Stats counters)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 変更ファイル一覧
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
core/box/hak_wrappers.inc.h (malloc/free wrapper統合, +2箇所)
|
|||
|
|
core/box/tiny_header_box.h (既存ビルド問題修正)
|
|||
|
|
Makefile (既存ビルド問題修正, +3箇所)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 重要な設計原則
|
|||
|
|
|
|||
|
|
1. **重複排除が主目的:**
|
|||
|
|
- FastLane 内で「同じ判定を二度しない」
|
|||
|
|
- 既存の hot handler を **呼ぶだけ** に留める
|
|||
|
|
|
|||
|
|
2. **Fail-Fast:**
|
|||
|
|
- 確信が持てない場合は必ず既存経路へ fallback
|
|||
|
|
- 単一フォールバック境界(FastLane → ColdFallback)
|
|||
|
|
|
|||
|
|
3. **ENV gate:**
|
|||
|
|
- Default ON(opt-out via `HAKMEM_FRONT_FASTLANE=0`)
|
|||
|
|
- A/B テストは同一バイナリで ENV トグル
|
|||
|
|
|
|||
|
|
4. **Stats 最小:**
|
|||
|
|
- hit/fallback のカウンタのみ
|
|||
|
|
- fallback reason は 3〜7 種類まで
|
|||
|
|
|
|||
|
|
## 次のステップ
|
|||
|
|
|
|||
|
|
### 昇格(強く推奨)
|
|||
|
|
|
|||
|
|
- `HAKMEM_FRONT_FASTLANE` を **default ON** として運用(opt-out 可)。
|
|||
|
|
- `core/bench_profile.h` の主要プリセットに `HAKMEM_FRONT_FASTLANE=1` を追加(A/B しやすさのため)。
|
|||
|
|
- Mixed 10-run / 健康診断を標準のチェック項目として残す(回帰検知)。
|
|||
|
|
|
|||
|
|
## 期待される効果
|
|||
|
|
|
|||
|
|
**設計書からの予測:**
|
|||
|
|
- **+1-3%** (reduce redundant checks + TLS reads)
|
|||
|
|
- wrapper→gate→policy→route の Layer Collapse
|
|||
|
|
- 境界の一本化による固定費削減
|
|||
|
|
|
|||
|
|
**既存の勝ち筋:**
|
|||
|
|
- Phase 2 B3 (Routing 分岐形): **+2.89%**
|
|||
|
|
- Phase 2 B4 (Wrapper Layer Hot/Cold Split): **+1.47%**
|
|||
|
|
- Combined: **~+4.4%**
|
|||
|
|
|
|||
|
|
Phase 6 はこれらとは異なるアプローチ(重複排除 + Layer Collapse)なので、相加効果が期待できます。
|
|||
|
|
|
|||
|
|
## 注意点
|
|||
|
|
|
|||
|
|
1. **ENV 漏れ防止:** 必ず `scripts/run_mixed_10_cleanenv.sh` を使う
|
|||
|
|
2. **別バイナリ比較にしない:** 削除/追加で A/B を崩さない
|
|||
|
|
3. **Cold を noinline,cold に追い出して Hot を太らせすぎない**
|
|||
|
|
4. **branch hint を固定しない:** モードで逆効果になり得る
|
|||
|
|
|
|||
|
|
## まとめ
|
|||
|
|
|
|||
|
|
Phase 6 Front FastLane (Layer Collapse) は **GO**:
|
|||
|
|
|
|||
|
|
- ✅ A/B 10-run: **+11.13%**(全 run でプラス)
|
|||
|
|
- ✅ 健康診断: PASS
|
|||
|
|
- ✅ 境界1箇所 + Fail-Fast の設計を維持したまま大幅改善
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**実装者:** Claude Sonnet 4.5
|
|||
|
|
**実装日:** 2025-12-14
|
|||
|
|
**ビルド:** Release (O3, LTO, native)
|
|||
|
|
**ENV:** `HAKMEM_FRONT_FASTLANE=1` (default ON, opt-out)
|