docs: freeze Phase 7 FastLane free hot/cold; add Phase 8 env cache fix
This commit is contained in:
@ -35,13 +35,21 @@
|
||||
- Phase 6-2: +5.18%
|
||||
- **累積**: ベースラインから約 +16-17% の性能向上
|
||||
|
||||
### Next: TBD(Phase 6 完了、次の芯を検討中)
|
||||
### Phase 7 FRONT-FASTLANE-FREE-HOTCOLD-ALIGNMENT: FastLane Free Hot/Cold Alignment — ❌ NO-GO / FROZEN
|
||||
|
||||
現状の候補(優先順):
|
||||
1) **Phase 7: FastLane Free Hot/Cold Alignment**
|
||||
- FastLane free が `free_tiny_fast()`(monolithic)固定で、既存の勝ち箱 `free_tiny_fast_hot()`(Hot/Cold + DUALHOT)が効かない “ねじれ” を解消する。
|
||||
- 指示書: `docs/analysis/PHASE7_FRONT_FASTLANE_FREE_HOTCOLD_1_NEXT_INSTRUCTIONS.md`
|
||||
- A/B: `HAKMEM_FREE_TINY_FAST_HOTCOLD=0/1`(同一バイナリ)
|
||||
結果: Mixed 10-run mean **-2.16%** 回帰。Hot/Cold split は wrapper 経由では有効だが、FastLane の超軽量経路では分岐/統計/TLS の固定費が勝ち、monolithic の方が速い。
|
||||
|
||||
- A/B 結果: `docs/analysis/PHASE7_FRONT_FASTLANE_FREE_HOTCOLD_1_AB_TEST_RESULTS.md`
|
||||
- 指示書(記録): `docs/analysis/PHASE7_FRONT_FASTLANE_FREE_HOTCOLD_1_NEXT_INSTRUCTIONS.md`
|
||||
- 対処: Rollback 済み(FastLane free は `free_tiny_fast()` 維持)
|
||||
|
||||
### Next: Phase 8(次の芯)
|
||||
|
||||
優先候補(GO を狙う小パッチ):
|
||||
1) **Phase 8: FREE-STATIC-ROUTE ENV cache hardening**
|
||||
- 症状: `HAKMEM_FREE_STATIC_ROUTE=1` を `bench_profile` で設定しても、プロセス初期の malloc/free で gate が先に 0 をキャッシュしてしまい、D1 が効かないことがある(`[FREE_STATIC_ROUTE] enabled` が出ない/`tiny_route_for_class` が perf に残る)。
|
||||
- 狙い: 既存の勝ち箱(Phase 3 D1)を “本当に” 有効化し、free の `tiny_route_for_class()` 固定費を削る。
|
||||
- 指示書: `docs/analysis/PHASE8_FREE_STATIC_ROUTE_ENV_CACHE_FIX_1_NEXT_INSTRUCTIONS.md`
|
||||
|
||||
## 更新メモ(2025-12-14 Phase 5 E5-3 Analysis - Strategic Pivot)
|
||||
|
||||
|
||||
@ -0,0 +1,220 @@
|
||||
# Phase 7: FastLane Free Hot/Cold Alignment A/B テスト結果
|
||||
|
||||
## 実装概要
|
||||
|
||||
**目的**: Phase 6 で FastLane free が `free_tiny_fast()`(monolithic)固定になっている不整合を解消し、既存の勝ち箱である `free_tiny_fast_hot()`(Hot/Cold + DUALHOT)を FastLane からも使えるようにする整合性修正。
|
||||
|
||||
**変更箇所**: `core/box/front_fastlane_box.h`(Phase 6-2 DeDup path)
|
||||
|
||||
**変更内容**:
|
||||
```c
|
||||
// 既存(monolithic 固定)
|
||||
int result = free_tiny_fast(ptr);
|
||||
|
||||
// 変更後(hot/cold alignment)
|
||||
int result = hak_free_tiny_fast_hotcold_enabled() ? free_tiny_fast_hot(ptr) : free_tiny_fast(ptr);
|
||||
```
|
||||
|
||||
## A/B テスト結果(Mixed 10-run clean env)
|
||||
|
||||
### A: hot/cold OFF(monolithic `free_tiny_fast()`)
|
||||
|
||||
```
|
||||
HAKMEM_FREE_TINY_FAST_HOTCOLD=0 scripts/run_mixed_10_cleanenv.sh
|
||||
```
|
||||
|
||||
| Run | Throughput (ops/s) |
|
||||
|-----|-------------------|
|
||||
| 1 | 46,492,972 |
|
||||
| 2 | 47,132,053 |
|
||||
| 3 | 46,330,554 |
|
||||
| 4 | 47,504,224 |
|
||||
| 5 | 47,520,766 |
|
||||
| 6 | 47,614,031 |
|
||||
| 7 | 46,634,189 |
|
||||
| 8 | 47,837,066 |
|
||||
| 9 | 46,866,762 |
|
||||
| 10 | 47,671,133 |
|
||||
|
||||
**統計**:
|
||||
- **Mean**: 47,160,375 ops/s
|
||||
- **Median**: 47,318,139 ops/s
|
||||
- **Stdev**: 544,734 ops/s (1.16%)
|
||||
|
||||
### B: hot/cold ON(`free_tiny_fast_hot()` 使用)
|
||||
|
||||
```
|
||||
HAKMEM_FREE_TINY_FAST_HOTCOLD=1 scripts/run_mixed_10_cleanenv.sh
|
||||
```
|
||||
|
||||
| Run | Throughput (ops/s) |
|
||||
|-----|-------------------|
|
||||
| 1 | 46,415,509 |
|
||||
| 2 | 46,427,235 |
|
||||
| 3 | 46,444,216 |
|
||||
| 4 | 45,939,083 |
|
||||
| 5 | 46,310,220 |
|
||||
| 6 | 45,688,278 |
|
||||
| 7 | 45,986,410 |
|
||||
| 8 | 46,372,681 |
|
||||
| 9 | 45,450,960 |
|
||||
| 10 | 46,378,735 |
|
||||
|
||||
**統計**:
|
||||
- **Mean**: 46,141,333 ops/s
|
||||
- **Median**: 46,341,451 ops/s
|
||||
- **Stdev**: 354,939 ops/s (0.77%)
|
||||
|
||||
### 性能差分
|
||||
|
||||
- **絶対値**: -1,019,042 ops/s
|
||||
- **パーセンテージ**: **-2.16%**
|
||||
|
||||
## 判定
|
||||
|
||||
**NO-GO (-1.0% 以下の回帰)**
|
||||
|
||||
FastLane free 経路で hot/cold split(`free_tiny_fast_hot()`)を使用すると、**-2.16%** の回帰が発生。
|
||||
|
||||
## 健康診断結果
|
||||
|
||||
```
|
||||
scripts/verify_health_profiles.sh
|
||||
```
|
||||
|
||||
- **MIXED_TINYV3_C7_SAFE**: 46,760,625 ops/s (正常)
|
||||
- **C6_HEAVY_LEGACY_POOLV1**: 21,800,899 ops/s (正常)
|
||||
|
||||
健康診断は両プロファイルとも正常に動作。
|
||||
|
||||
## 原因分析
|
||||
|
||||
### 1. Hot/Cold split のオーバーヘッド
|
||||
|
||||
`free_tiny_fast_hot()` は以下の追加オーバーヘッドを含む:
|
||||
|
||||
1. **統計カウンタ**: `FREE_TINY_FAST_HOTCOLD_STAT_INC()` マクロ(複数箇所)
|
||||
2. **Cold path への分岐**: `free_tiny_fast_cold()` へのコールオーバーヘッド
|
||||
3. **TLS アクセス**: 統計カウンタ用の TLS 変数アクセス
|
||||
|
||||
### 2. FastLane DeDup 経路の特性
|
||||
|
||||
Phase 6 の FastLane free DeDup 経路は:
|
||||
|
||||
- **ヘッダ検証を 1 回だけ実施**(FastLane 内で完結)
|
||||
- **最小限の分岐**で高速化を狙う設計
|
||||
- **monolithic `free_tiny_fast()` の方が I-cache locality が良好**
|
||||
|
||||
Hot/Cold split は wrapper 経路(複数分岐あり)では有効だが、FastLane の超軽量経路では逆効果。
|
||||
|
||||
### 3. DUALHOT との整合性問題
|
||||
|
||||
指示書では「既存の勝ち箱を FastLane に通す」とあるが、実際には:
|
||||
|
||||
- **wrapper 経路**: 複数分岐 → hot/cold split で I-cache 改善 → 勝ち
|
||||
- **FastLane 経路**: 単一分岐 → hot/cold split で I-cache 悪化 → 負け
|
||||
|
||||
環境の違いにより、同じ最適化が逆効果になるケース。
|
||||
|
||||
## 次のステップ
|
||||
|
||||
### Option 1: Rollback(推奨)
|
||||
|
||||
`HAKMEM_FREE_TINY_FAST_HOTCOLD=0` をデフォルトに戻す。
|
||||
|
||||
- FastLane free は monolithic `free_tiny_fast()` のまま(Phase 6 の勝ち筋維持)
|
||||
- wrapper 経由の free は引き続き hot/cold split 可能(環境変数で切り替え)
|
||||
|
||||
### Option 2: 条件付き hot/cold split
|
||||
|
||||
FastLane 経路では強制的に monolithic を使い、wrapper 経由の場合のみ hot/cold split を有効化:
|
||||
|
||||
```c
|
||||
// FastLane 経路では常に monolithic(統計オーバーヘッド回避)
|
||||
int result = free_tiny_fast(ptr);
|
||||
```
|
||||
|
||||
wrapper 側:
|
||||
```c
|
||||
// wrapper 経由では hot/cold split 可能
|
||||
if (hak_free_tiny_fast_hotcold_enabled()) {
|
||||
return free_tiny_fast_hot(ptr);
|
||||
} else {
|
||||
return free_tiny_fast(ptr);
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: 研究継続(FastLane 専用 hot/cold)
|
||||
|
||||
FastLane 専用の軽量 hot/cold split を設計:
|
||||
|
||||
- 統計カウンタを削除(DEBUG ビルドのみ)
|
||||
- cold path を inline 化して分岐コストを最小化
|
||||
- DUALHOT 最適化のみを適用(C0-C3 直接 legacy fallback)
|
||||
|
||||
ただし、追加研究コストに見合う効果が出るかは不明。
|
||||
|
||||
## Rollback 手順
|
||||
|
||||
現在の実装を Phase 6 の状態に戻す:
|
||||
|
||||
```c
|
||||
// core/box/front_fastlane_box.h(Phase 6-2 DeDup path)
|
||||
// 変更前に戻す
|
||||
int result = free_tiny_fast(ptr);
|
||||
```
|
||||
|
||||
再ビルド:
|
||||
```sh
|
||||
make clean && make bench_random_mixed_hakmem
|
||||
```
|
||||
|
||||
確認:
|
||||
```sh
|
||||
HAKMEM_FREE_TINY_FAST_HOTCOLD=0 scripts/run_mixed_10_cleanenv.sh
|
||||
```
|
||||
|
||||
## Rollback 実施
|
||||
|
||||
`front_fastlane_box.h` を Phase 6 の状態に戻しました:
|
||||
|
||||
```c
|
||||
// Phase 6-2: DeDup path (eliminate duplicate header validation)
|
||||
// Conditions:
|
||||
// 1. Free DeDup enabled (ENV=1)
|
||||
// 2. All classes enabled (mask=0xFF, no gradual rollout)
|
||||
if (__builtin_expect(front_fastlane_free_dedup_enabled() && front_fastlane_class_mask() == 0xFF, 1)) {
|
||||
// Direct call to free_tiny_fast() (handles all validation internally)
|
||||
// free_tiny_fast() is static inline in malloc_tiny_fast.h, no extern needed
|
||||
int result = free_tiny_fast(ptr);
|
||||
if (__builtin_expect(result, 1)) {
|
||||
FRONT_FASTLANE_STAT_INC(free_hit);
|
||||
return true; // Handled
|
||||
}
|
||||
// Not handled → fallback
|
||||
FRONT_FASTLANE_STAT_INC(free_fallback_failure);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
**確認テスト**:
|
||||
```sh
|
||||
./bench_random_mixed_hakmem 20000000 400 5
|
||||
# Throughput = 47.9M ops/s (正常)
|
||||
```
|
||||
|
||||
## 結論
|
||||
|
||||
Phase 7 の FastLane free hot/cold alignment は **-2.16% の回帰(NO-GO)** が発生し、Rollback を実施。
|
||||
|
||||
**原因**: FastLane の超軽量経路(DeDup)では、hot/cold split の統計カウンタと分岐オーバーヘッドが逆効果。wrapper 経由の複雑経路では有効な最適化だが、FastLane の単純経路では monolithic の方が高速。
|
||||
|
||||
**推奨**: Phase 6 の勝ち筋(monolithic `free_tiny_fast()`)を維持。wrapper 経由は引き続き hot/cold split 可能(環境変数制御)。
|
||||
|
||||
**教訓**: 同じ最適化でも、経路の複雑さ(分岐数、I-cache locality)により効果が逆転するケースがある。FastLane は「最小限の分岐」が勝ちパターン。
|
||||
|
||||
**整合性問題への対処**:
|
||||
- 当初の狙い「wrapper と FastLane の整合性」は、性能回帰により見送り
|
||||
- FastLane と wrapper は異なる最適化戦略を持つ独立した経路として扱う
|
||||
- wrapper: 複雑経路 → hot/cold split で I-cache 改善
|
||||
- FastLane: 単純経路 → monolithic で分岐最小化
|
||||
@ -1,5 +1,14 @@
|
||||
# Phase 7: FastLane Free Hot/Cold Alignment(次の指示書)
|
||||
|
||||
## Status(2025-12-14)
|
||||
|
||||
**❌ NO-GO / FROZEN**(Mixed 10-run mean **-2.16%** 回帰、Rollback 実施済み)
|
||||
|
||||
- A/B 結果: `docs/analysis/PHASE7_FRONT_FASTLANE_FREE_HOTCOLD_1_AB_TEST_RESULTS.md`
|
||||
- 結論: FastLane free は monolithic `free_tiny_fast()` を維持し、wrapper 経由は引き続き `HAKMEM_FREE_TINY_FAST_HOTCOLD=1` で hot/cold を使う(経路ごとに最適化戦略を分ける)。
|
||||
|
||||
このドキュメントは「試した設計の記録」として保持する(再挑戦するなら FastLane 専用の statsless/hintless hot/cold を別箱で設計し直す)。
|
||||
|
||||
## 0. 目的(狙い)
|
||||
|
||||
Phase 6 で FastLane(default ON)+ Free DeDup(default ON)まで本線化できた。次は **FastLane free が `free_tiny_fast()`(monolithic)固定になっている不整合**を解消し、既存の勝ち箱である **`free_tiny_fast_hot()`(Hot/Cold + DUALHOT)** を FastLane からも使えるようにする。
|
||||
@ -96,4 +105,3 @@ scripts/verify_health_profiles.sh
|
||||
- さらに戻すなら
|
||||
- `HAKMEM_FRONT_FASTLANE_FREE_DEDUP=0`
|
||||
- `HAKMEM_FRONT_FASTLANE=0`
|
||||
|
||||
|
||||
@ -0,0 +1,105 @@
|
||||
# Phase 8: FREE-STATIC-ROUTE ENV cache hardening(次の指示書)
|
||||
|
||||
## 0. 目的(狙い)
|
||||
|
||||
Phase 3 D1(`HAKMEM_FREE_STATIC_ROUTE=1`)は「`tiny_route_for_class()` の固定費を消す」勝ち箱だが、**プロセス初期の malloc/free(main 前)で ENV gate が先に 0 をキャッシュ**すると、`bench_profile` が後から `putenv()` で `HAKMEM_FREE_STATIC_ROUTE=1` を設定しても D1 が効かないことがある。
|
||||
|
||||
この Phase は **“既に採用している最適化が確実に効く状態” を作る**(= 本線品質)ことが目的。
|
||||
|
||||
## 1. 症状(観測)
|
||||
|
||||
- `core/bench_profile.h` は `HAKMEM_FREE_STATIC_ROUTE=1` をセットしているのに、実行ログに `[FREE_STATIC_ROUTE] enabled` が出ないことがある。
|
||||
- perf で `tiny_route_for_class` が残る(例: self ~2–3%)。
|
||||
|
||||
## 2. 根本原因
|
||||
|
||||
`core/box/tiny_free_route_cache_env_box.h` の gate が **“ENV 未設定 → 即 0 を確定”**してしまうため。
|
||||
|
||||
- `bench_profile` の `putenv()` より前に `tiny_free_static_route_enabled()` が 1 回でも呼ばれると、
|
||||
- `g_free_static_route_enabled = 0` が確定し、以後 `getenv()` を見ない。
|
||||
- その後 `bench_profile` が `HAKMEM_FREE_STATIC_ROUTE=1` を設定しても、hot path は OFF のまま。
|
||||
|
||||
(同型の問題を避けるため、`HAKMEM_TINY_ALLOC_DUALHOT` や `HAKMEM_FREE_TINY_FAST_HOTCOLD` は “probe window” を持っている。)
|
||||
|
||||
## 3. 方針(Box Theory)
|
||||
|
||||
### 箱
|
||||
|
||||
- L0: `FreeStaticRouteEnvGateBox`(この Phase)
|
||||
- 「ENV を読む/キャッシュする」をここに閉じ込める
|
||||
- `bench_profile` から **refresh** できるようにする(戻せる/同期できる)
|
||||
|
||||
### 境界
|
||||
|
||||
- `tiny_free_static_route_enabled()` は **hot inline** のまま維持
|
||||
- `bench_profile` から `*_refresh_from_env()` を 1 回だけ呼べるようにする(変換点 1 箇所)
|
||||
|
||||
## 4. 実装指示(小パッチ順)
|
||||
|
||||
### Patch 1: ENV gate を “refresh 可能” にする(推奨)
|
||||
|
||||
対象: `core/box/tiny_free_route_cache_env_box.h`
|
||||
|
||||
やること:
|
||||
- header 内 `static int g_free_static_route_enabled` を廃止し、**単一のグローバル状態**に寄せる
|
||||
- `extern _Atomic int g_free_static_route_enabled;`(-1/0/1)
|
||||
- `tiny_free_static_route_refresh_from_env()` を追加
|
||||
- `g_free_static_route_enabled = -1` に戻して次回 `getenv()` させる(Fail-Fast: “確信がないなら読み直す”)
|
||||
- 可能なら refresh 内で `getenv()` して 0/1 を確定してもよい(どちらでも OK、ただし hot path に影響させない)
|
||||
|
||||
新規: `core/box/tiny_free_route_cache_env_box.c`
|
||||
- `g_free_static_route_enabled` の定義と refresh 実装
|
||||
|
||||
### Patch 2: bench_profile の “ENV 反映” に組み込む
|
||||
|
||||
対象: `core/bench_profile.h`
|
||||
|
||||
`bench_apply_profile()` の `bench_setenv_default()` 群の後にある refresh 群に追加:
|
||||
- `tiny_free_static_route_refresh_from_env();`
|
||||
|
||||
目的:
|
||||
- `putenv()` で設定した値が gate に確実に反映される(main 前のキャッシュ事故を無効化)
|
||||
|
||||
### Patch 3: 可視化(最小)
|
||||
|
||||
- `[FREE_STATIC_ROUTE] enabled` は “1回だけ” 出るように維持(多重出力は避ける)
|
||||
- 追加カウンタを増やさない(必要なら 1 個だけ)
|
||||
|
||||
## 5. A/B(同一バイナリ)
|
||||
|
||||
### Mixed 10-run(clean env)
|
||||
|
||||
Baseline:
|
||||
```sh
|
||||
HAKMEM_FREE_STATIC_ROUTE=0 scripts/run_mixed_10_cleanenv.sh
|
||||
```
|
||||
|
||||
Optimized:
|
||||
```sh
|
||||
HAKMEM_FREE_STATIC_ROUTE=1 scripts/run_mixed_10_cleanenv.sh
|
||||
```
|
||||
|
||||
判定(Mixed 10-run mean):
|
||||
- GO: **+1.0% 以上**
|
||||
- NEUTRAL: **±1.0%**
|
||||
- NO-GO: **-1.0% 以下**
|
||||
|
||||
追加チェック(必須):
|
||||
- `HAKMEM_FREE_STATIC_ROUTE=1` で `[FREE_STATIC_ROUTE] enabled` が出ること
|
||||
|
||||
### perf(任意)
|
||||
|
||||
期待:
|
||||
- `tiny_route_for_class` が top から落ちる/低下する
|
||||
|
||||
## 6. 健康診断(必須)
|
||||
|
||||
```sh
|
||||
scripts/verify_health_profiles.sh
|
||||
```
|
||||
|
||||
## 7. Rollback
|
||||
|
||||
- `HAKMEM_FREE_STATIC_ROUTE=0`
|
||||
- もしくは Patch 1/2 を revert
|
||||
|
||||
Reference in New Issue
Block a user