Files
hakmem/CURRENT_TASK.md

116 lines
12 KiB
Markdown
Raw Normal View History

## HAKMEM 状況メモ (2025-12-05 更新 / C7 Warm/TLS Bind 反映)
### 現在の状態Tiny / Superslab / Warm Pool
- Tiny Front / Superslab / Shared Pool は Box Theory 準拠で 3 層構造に整理済みHOT/WARM/COLD
- Tiny Gatekeeper Boxalloc/freeと Tiny Route Box により、USER→BASE 変換と Tiny vs Pool のルーティングを入口 1 箇所に集約。
- Superslab Tier BoxHOT/DRAINING/FREE Release Guard Box により、SuperSlab ライフサイクルと eager FREE の安全な境界を定義。
- Warm Pool 層:
- `tiny_warm_pool.h`: per-thread の HOT SuperSlab プール。
- `warm_pool_stats_box.h`: hits/misses/prefilled の統計箱。
- `warm_pool_prefill_box.h`: registry スキャン時に Warm Pool を事前充填する cold-path helper。
- Prefault Box`ss_prefault_box.h`は追加済みだが、4MB MAP_POPULATE 問題を避けるためデフォルト OFF`HAKMEM_SS_PREFAULT=0`)に設定。
### 直近の成果
- Gatekeeper inliningPhase A-1完了`malloc`/`free` ラッパの関数呼び出しを削減しつつ、Box 境界は維持。
- Unified Cache Refill の debug 検証を 1 箇所に集約し、リリースビルドの HOT パスを軽量化:
- `bench_random_mixed_hakmem 1000000 256 42` が約 4.3M → 5.0M ops/s~+17%)に改善。
- Tiny-only/Tiny Mixed / Non-Tiny の条件差分をドキュメント化・分離:
- `bench_random_mixed_hakmem``HAKMEM_BENCH_MIN_SIZE` / `HAKMEM_BENCH_MAX_SIZE` を追加し、
- 8128BTiny-only
- 1291024BTiny C5C7 専用)
を個別に測定可能にした。
- `docs/PERF_ANALYSIS_TINY_MIXED.md` ほかに、8128B/200K/ws=400旧 Tiny 専用)と現在の 161024B/1M/ws=256Tiny+Non-Tiny 混在)の違いを明記。
- Unified Cache Refill 安全化Step 1 完了):
- `core/front/tiny_unified_cache.c``unified_cache_refill()``max_batch <= 256` を保証し、`out[256]` と常に整合するよう修正。
- C5〜C7 の Unified Cache 容量・バッチサイズを増やす実験を行ってもスタック破壊が起きない状態にした。
- Tiny Page BoxC7 Tiny-Plus 層の導入Step 2 第1段階完了:
- `core/box/tiny_page_box.h` / `core/box/tiny_page_box.c` を追加し、`HAKMEM_TINY_PAGE_BOX_CLASSES` で有効クラスを制御できる Page Box を実装。
- `tiny_tls_bind_slab()` から `tiny_page_box_on_new_slab()` を呼び出し、TLS が bind した C7 slab を per-thread の page pool に登録。
- `unified_cache_refill()` の先頭に Page Box 経路を追加し、C7 では「TLS が掴んでいるページ内 freelist/carve」からバッチ供給を試みてから Warm Pool / Shared Pool に落ちるようにしたBox 境界は `Tiny Page Box → Warm Pool → Shared Pool` の順序を維持)。
- TinyClassPolicy/Stats/Learner Box を追加し、Hot path は `tiny_policy_get(class_idx)` で Page/Warm ポリシーを読むだけに統一。
- FROZEN デフォルトlegacy プロファイルPage Box は C5〜C7 のみ ON、Warm は C0〜C7 すべて ONC0〜C4 cap=4、C5〜C7 cap=8
- ENV `HAKMEM_TINY_POLICY_PROFILE=legacy|c5_7_only|tinyplus_all` で切替可能(未指定は legacy
- Stats は OBSERVE 用に積むだけ、Learner は空実装のまま。
- TLS Bind Box の導入:
- `core/box/ss_tls_bind_box.h``ss_tls_bind_one()` を追加し、「Superslab + slab_idx → TLS」のバインド処理`superslab_init_slab` / `meta->class_idx` 設定 / `tiny_tls_bind_slab`)を 1 箇所に集約。
- `superslab_refill()`Shared Pool 経路)および Warm Pool 実験経路から、この Box を経由して TLS に接続するよう統一。
- C7 Warm/TLS Bind 経路の実装と検証:
- `core/front/tiny_unified_cache.c` に C7 専用の Warm/TLS Bind モード0/1/2を追加し、Debug では `HAKMEM_WARM_TLS_BIND_C7` で切替可能にした。
- mode 0: Legacy Warmレガシー/デバッグ用、C7 では carve 0 が多く非推奨)
- mode 1: Bind-onlyWarm から取得した Superslab を TLS Bind Box 経由でバインドする本番経路)
- mode 2: Bind+TLS carveTLS から直接 carve する実験経路)
- Release ビルドでは常に mode=1 固定。Debug では `HAKMEM_WARM_TLS_BIND_C7=0/1/2` で切替。
- Warm Pool / Unified Cache の詳細計測:
- `warm_pool_dbg_box.h` と Unified Cache の計測フックを拡張し、C7 向けに
- Warm pop 試行/ヒット/実 carve 回数
- TLS carve 試行/成功/失敗
- UC ミスを Warm/TLS/Shared 別に分類
を Debug ビルドで観測可能にした。
- `bench_random_mixed.c``HAKMEM_BENCH_C7_ONLY=1` を追加し、C7 サイズ専用の micro-bench を追加。
- TinyClassPolicy / Stats / Learner Box の導入(初期フェーズ):
- `core/box/tiny_class_policy_box.{h,c}` にクラス別ポリシー構造体 `TinyClassPolicy``tiny_policy_get(class_idx)` を追加。
- FROZEN デフォルト: Page Box = C5C7, Warm = 全クラスC0C4 cap=4 / C5C7 cap=8
- `HAKMEM_TINY_POLICY_PROFILE=legacy|c5_7_only|tinyplus_all` でプロファイル切替可能(未知値は legacy にフォールバック)。
- `core/box/tiny_class_stats_box.{h,c}` に OBSERVE 用の軽量カウンタUC miss / Warm hit / Shared Pool lock など)を追加。
- `core/box/tiny_policy_learner_box.{h,c}` に Learner の骨組みを追加(現状は FROZEN/OBSERVE モード向けの雛形)。
- `core/front/tiny_unified_cache.c` / Page Box / Warm Pool 経路を `tiny_policy_get(class_idx)` ベースでゲートし、Hot path からは Policy Box を読む形に統一。
### 性能の現状Random Mixed, HEAD
- 注記 (2025-12-05, policy legacy プロファイル試験値):
- Release: `HAKMEM_TINY_PROFILE=full HAKMEM_TINY_POLICY_PROFILE=legacy ./bench_random_mixed_hakmem 1000000 256 42` → 約 4.9M ops/s導入前 27M との乖離あり、要フォロー)。
- Release C7-only: `HAKMEM_BENCH_C7_ONLY=1 ... HAKMEM_TINY_POLICY_PROFILE=legacy` → 約 2.7M ops/s空スラブガード導入前の遅さに戻っており要再調査
- 条件: `bench_random_mixed_hakmem 1000000 256 42`1T, ws=256, RELEASE, 161024B
- HAKMEM: 約 27.6M ops/sC7 Warm/TLS 修復後)
- system malloc: 約 90100M ops/s
- mimalloc: 約 120130M ops/s
- 条件: `bench_random_mixed_hakmem 1000000 256 42` +
`HAKMEM_BENCH_MIN_SIZE=8 HAKMEM_BENCH_MAX_SIZE=128`Tiny-only, 8128B
- HAKMEM Tiny Front: 約 8090M ops/smimalloc と同オーダー)
- 条件: `bench_random_mixed_hakmem 1000000 256 42` +
`HAKMEM_BENCH_MIN_SIZE=129 HAKMEM_BENCH_MAX_SIZE=1024`Tiny C5C7 のみ)
- HAKMEM: 約 28.0M ops/sWarm/TLS ガード適用後)
- 条件: C7 専用 micro-benchDebug, `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_PROFILE=full HAKMEM_WARM_C7_MAX=8 HAKMEM_WARM_C7_PREFETCH=4` ほか)
- mode 0Legacy Warm: 約 2.0M ops/s、C7 Warm ヒット 0・Shared Pool ロック多数(`slab_carve_from_ss` が 0 を頻発)
- mode 1Bind-only: 約 20M ops/siters=200K, ws=32、Warm hit ≈100%・Shared Pool ロック 5 回まで減少
- mode 2Bind+TLS carve 実験): mode 1 と同等〜わずかに上UC ミスは増えるが `uc_miss_tls` に集中し、avg_refill は短縮)
- 条件: C7 専用 micro-benchRelease, `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_PROFILE=full HAKMEM_WARM_C7_MAX=8 HAKMEM_WARM_C7_PREFETCH=4`
- HAKMEM: 約 18.8M ops/s空スラブ強制ガード + リセット導入後、Debug と同オーダーまで回復)
- 結論:
- Tiny front 自体8128Bは十分速く、mimalloc と同オーダーまで出ている。
- C5C7 経路は「満杯 C7 slab を Warm に再供給していた」問題を空スラブ限定ガードRelease/Debug 共通リセットで解消し、
C7-only Release も ~18.8M ops/s に回復。Random Mixed Release も 27M クラスまで改善。
### 次にやること(広い条件での安定化確認)
1. `HAKMEM_BENCH_MIN_SIZE=129 HAKMEM_BENCH_MAX_SIZE=1024` や通常の `bench_random_mixed_hakmem 1000000 256 42`
空スラブ限定ガードが副作用なく動くかを継続確認(現状 Release で 2728M ops/s を確認済み)。
2. ドキュメント更新:
- Release だけ C7 Warm が死んでいた根本原因 = 満杯 C7 slab を Shared Pool がリセットせず再供給していた。
- Acquire の空スラブ強制ガードRelease/Debug 共通リセットで C7-only Release が ~18.8M ops/s まで回復した。
3. 次フェーズ案:
- C5/C6 でも同様の Warm/TLS 最適化・空スラブガードを適用するか、
- Random Mixed 全体のボトルネックShared Pool ロック/Wrapper/mid-size path など)を洗うかを選択。
### 次フェーズTiny 全クラス向け Page Box / Warm / Policy 汎用化の検討)
- 方向性:
- 現在は C7 向け Tiny-PlusPage Box + Warm Pool + TLS Bindが安定したため、C1〜C7 まで「候補」として広げつつ、
実際にどのクラスで有効化するかは Policy Box学習/ENV側で制御する設計に進める。
- 設計方針(案):
- `TinyClassPolicyBox` を新設し、クラス別ポリシー構造体(`TinyClassPolicy{ page_box_enabled, warm_enabled, warm_cap, ... }`)を配列で保持。
- Hot pathTiny Front / Unified Cache / Page Box / Warm Pool`tiny_policy_get(class_idx)` でポリシーを読むだけにし、
学習/更新は `TinyPolicyLearnerBox` 側で行う。
- `TinyClassStatsBox` を導入し、クラス別に UC miss / warm hit / shared_pool_lock などの軽量カウンタを記録OBSERVE/LEARN モード用)。
- モードは FROZEN / OBSERVE / LEARN を ENV で切替可能にし、デフォルトは FROZENC5C7 のみ Page Box/Warm ON, 他クラス OFF
- 実装ステップ(案):
1. C7 Page Box / Warm / TLS Bind の API を「class_idx を引数に取る汎用形」に整理し、内部で `if (!policy->page_box_enabled) fallback` する形にリファクタ。
2. `TinyClassPolicy` struct と `tiny_policy_get(class_idx)` を導入し、Hot path から直接 `HAKMEM_*` ENV を参照しないようにするPolicy Box 経由に統一)。
3. `TinyClassStatsBox` を追加し、FROZEN/OBSERVE モードで C1〜C7 の stats を集計policy はまだ固定)。
4. `TinyPolicyLearnerBox` を追加し、LEARN モードで stats をもとに `page_box_enabled[]` / `warm_cap[]` を更新(ただし「同時に ON にできるクラス数」に上限を設ける)。
- 進捗メモ(実装済み):
- `TinyClassPolicyBox`/`TinyClassStatsBox`/`TinyPolicyLearnerBox` を追加し、デフォルトで C5〜C7 に Page Box + Warm を許可Warm cap=8
- unified_cache_refill の Page/Warm 経路は `tiny_policy_get()` の返り値でゲートし、Warm push は per-class cap を尊重。
- Page Box 初期化もデフォルトで C5〜C7 を有効化。OBSERVE 用の軽量 stats increment を UC miss / Warm hit に接続済み。
### メモ
- ページフォルト問題は Prefault Box + ウォームアップで一定水準まで解消済みで、現在の主ボトルネックはユーザー空間の箱Unified Cache / free / Pool側に移っている。
- 以降の最適化は「箱を削る」ではなく、「HOT 層で踏む箱を減らし、Tiny 的なシンプル経路と Tiny-Plus 経路Page Box + Warmをクラス別ポリシーでどう使い分けるか」にフォーカスする。