117 lines
4.7 KiB
Markdown
117 lines
4.7 KiB
Markdown
|
|
# Phase 4 E1: ENV Snapshot Consolidation(設計メモ)
|
|||
|
|
|
|||
|
|
## 目的
|
|||
|
|
|
|||
|
|
ホットパスで毎回呼ばれている ENV gate(小さな関数)の呼び出し/分岐/TLS参照を **1 回の “snapshot load” に集約**し、
|
|||
|
|
MIXED の「shape 最適化の頭打ち」を越える。
|
|||
|
|
|
|||
|
|
ターゲット(直近 perf self%):
|
|||
|
|
- `tiny_c7_ultra_enabled_env()` ≈ 1.28%
|
|||
|
|
- `tiny_front_v3_enabled()` ≈ 1.01%
|
|||
|
|
- `tiny_metadata_cache_enabled()` ≈ 0.97%
|
|||
|
|
- 合計 ≈ **3.26%**
|
|||
|
|
|
|||
|
|
※ self% はそのまま speedup にはならないが、Hot loop で “毎回” 評価される小関数群が占める割合として無視できない。
|
|||
|
|
|
|||
|
|
## 背景(何が起きているか)
|
|||
|
|
|
|||
|
|
- Phase 2–3 の “分岐形(shape)” 最適化は一定効いたが、D3 が NEUTRAL になり **形だけでは頭打ち**。
|
|||
|
|
- 現状は「ENV gate を 3 回別々に呼ぶ」ため、
|
|||
|
|
- 小関数 call(inlining されないケース)
|
|||
|
|
- lazy init の分岐(TU-local static / probe window)
|
|||
|
|
- TLS 参照(policy hot TLS 等)
|
|||
|
|
が積み上がる。
|
|||
|
|
- さらに `__builtin_expect(..., 0)` が **実態(default ON)と逆**の場所があり、分岐予測を損ねている可能性が高い。
|
|||
|
|
|
|||
|
|
## 非目標
|
|||
|
|
|
|||
|
|
- ルーティングやアルゴリズムの変更(意味を変えない)
|
|||
|
|
- Learner の挙動変更(interlock を壊さない)
|
|||
|
|
- 常時ログ増加(ワンショット/統計のみ)
|
|||
|
|
|
|||
|
|
## 箱割り(Box Theory)
|
|||
|
|
|
|||
|
|
### L0: EnvSnapshotBox(設定を 1 箱に集約)
|
|||
|
|
|
|||
|
|
新規 Box:
|
|||
|
|
- `core/box/hakmem_env_snapshot_box.h`
|
|||
|
|
- `core/box/hakmem_env_snapshot_box.c`
|
|||
|
|
|
|||
|
|
責務:
|
|||
|
|
- ENV を 1 回だけ読んで “Hot に必要な bool 値” を構造体に凍結する
|
|||
|
|
- bench_profile の `putenv()` 後に refresh できる(戻せる)
|
|||
|
|
|
|||
|
|
### L1: Call-site Migration(境界 1 箇所ずつ置換)
|
|||
|
|
|
|||
|
|
既存の ENV gate を “呼ばない” 方向で、以下の call-site を段階的に置換する。
|
|||
|
|
(既存 gate 関数は残し、E1 を OFF に戻せる)
|
|||
|
|
|
|||
|
|
対象(最小セット):
|
|||
|
|
- `tiny_c7_ultra_enabled_env()` → snapshot フィールド参照
|
|||
|
|
- `tiny_front_v3_enabled()` → snapshot フィールド参照(or snapshot から front_snap を得る)
|
|||
|
|
- `tiny_metadata_cache_enabled()` → snapshot フィールド参照(learner interlock を含んだ “effective” 値)
|
|||
|
|
|
|||
|
|
## API(案)
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
typedef struct HakmemEnvSnapshot {
|
|||
|
|
int inited;
|
|||
|
|
int enabled; // ENV: HAKMEM_ENV_SNAPSHOT=0/1(default 0)
|
|||
|
|
|
|||
|
|
// Hot toggles (effective values)
|
|||
|
|
int tiny_front_v3_enabled; // default 1
|
|||
|
|
int tiny_c7_ultra_enabled; // default 1
|
|||
|
|
int tiny_metadata_cache; // default 0
|
|||
|
|
int tiny_metadata_cache_eff; // tiny_metadata_cache && !learner
|
|||
|
|
} HakmemEnvSnapshot;
|
|||
|
|
|
|||
|
|
const HakmemEnvSnapshot* hakmem_env_snapshot_get_fast(void);
|
|||
|
|
void hakmem_env_snapshot_refresh_from_env(void);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
設計ノート:
|
|||
|
|
- `*_eff` を持たせ、call-site から `small_learner_v2_enabled()` の呼び出しを除去する
|
|||
|
|
- `enabled` は refresh 時に 1 回だけ決め、Hot では分岐を増やさない(できれば compile-out)
|
|||
|
|
|
|||
|
|
## 初期化と bench_profile(putenv 問題)
|
|||
|
|
|
|||
|
|
bench では `bench_setenv_default()` が `putenv()` を使うため、lazy init が先に走ると “誤った 0” を掴む。
|
|||
|
|
対策は既存方針に合わせる:
|
|||
|
|
- `core/bench_profile.h` の最後で `hakmem_env_snapshot_refresh_from_env()` を必ず呼ぶ
|
|||
|
|
- `wrapper_env_refresh_from_env()` / `tiny_static_route_refresh_from_env()` と同じ “ENV 同期箱” 扱い
|
|||
|
|
|
|||
|
|
## 移行対象(最小)
|
|||
|
|
|
|||
|
|
まずは “毎回評価される” ところを最小パッチで狙う:
|
|||
|
|
- `core/front/malloc_tiny_fast.h`(alloc/free の hot path)
|
|||
|
|
- `core/box/tiny_legacy_fallback_box.h`(free の第2ホット)
|
|||
|
|
- `core/box/tiny_metadata_cache_hot_box.h`(policy hot 入口)
|
|||
|
|
- `core/box/free_policy_fast_v2_box.h`(研究箱だが整合)
|
|||
|
|
|
|||
|
|
## A/B(GO/NO-GO)
|
|||
|
|
|
|||
|
|
### ベンチ
|
|||
|
|
- Mixed(10-run, iter=20M, ws=400, 1T)
|
|||
|
|
- Baseline: `HAKMEM_ENV_SNAPSHOT=0`
|
|||
|
|
- Opt: `HAKMEM_ENV_SNAPSHOT=1`
|
|||
|
|
|
|||
|
|
### 判定
|
|||
|
|
- GO: **mean +2.5% 以上**(目標) かつ crash/assert なし
|
|||
|
|
- NEUTRAL: ±1% 以内 → research box 維持(default OFF)
|
|||
|
|
- NO-GO: -1% 以下 → freeze
|
|||
|
|
|
|||
|
|
### 検証(必須)
|
|||
|
|
- perf で `tiny_c7_ultra_enabled_env/tiny_front_v3_enabled/tiny_metadata_cache_enabled` の self% が **明確に減る**こと
|
|||
|
|
- 本線プロファイル(MIXED_TINYV3_C7_SAFE)で regression がないこと
|
|||
|
|
|
|||
|
|
## リスクと回避
|
|||
|
|
|
|||
|
|
- **MEDIUM(refactor/置換)**:
|
|||
|
|
- 置換は “最小 3 gate” から始め、段階的に広げる
|
|||
|
|
- 失敗したら `HAKMEM_ENV_SNAPSHOT=0` で即戻す
|
|||
|
|
- **初期化順序**:
|
|||
|
|
- bench_profile に refresh を追加して putenv 後の SSOT を保証
|
|||
|
|
- **Learner interlock**:
|
|||
|
|
- `tiny_metadata_cache_eff` の計算で learner を必ず抑制
|
|||
|
|
|