Guard madvise ENOMEM and stabilize pool/tiny front v3

This commit is contained in:
Moe Charm (CI)
2025-12-09 21:50:15 +09:00
parent e274d5f6a9
commit a905e0ffdd
45 changed files with 3154 additions and 242 deletions

View File

@ -6,6 +6,31 @@ TinyHeap v2 Design (入口メモ)
- C7 専用で「1 枚 lease + current/freelist を v2 で握る」状態。ページ供給・meta/ss_active/Remote/Stats はすべて v1 TinyHeap/C7 SAFE に委譲。
- A/B でいつでも v1 に戻せる(`HAKMEM_TINY_HOTHEAP_V2` / `HAKMEM_TINY_HOTHEAP_CLASSES`)。性能はまだ v1 と同等を維持するのが目的。
現状評価サマリ (Phase66 時点)
----------------------------
- C7 v2:
- C7-only / Mixed 161024B の長尺プロファイルws=400, iters=1M, PROFILE=C7_SAFEでは、v2 ON/OFF いずれも `HEAP_STATS[7].slow≈1`・refill≈1 に収束し、性能も v1 比で ±5% 以内(むしろ数%プラス)。
- 短尺20k/ws=64の refill≒50 はウォームアップ由来であり、本命プロファイルには影響しないことを確認。
- デフォルト構成では `HAKMEM_TINY_HOTHEAP_V2=0` を維持しつつ、C7-only の bench/pro 用プロファイルでは `HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80` を opt-in 推奨とする。本線候補としては「C7 SAFE v1/v2 並列」の状態。
- C6 v2:
- route/gate 修正後も C6-heavy / Mixed で大幅な回帰が残っており、C6-only v2 ON は v1 より明確に遅い。
- 現状は構造レベルでは通電しているが perf 未達のため、「研究箱」として `HAKMEM_TINY_HOTHEAP_CLASSES=0x40/0xC0` を明示したときだけ有効にし、標準プロファイルでは必ず OFF にする。
Phase63: C6 v2 を opt-in で拡張(ベンチ結果は要改善)
-----------------------------------------------
- 実装: v2 Hot Box を class_idx パラメータ化し、C6 も `HAKMEM_TINY_HOTHEAP_CLASSES` の bit6 で有効化可能にした。stats もクラス配列化し、C6/C7 両方で route_hits / refill / fallback を追跡。TLS 初期化で C6 も stride と max_partial_pages=2 を設定。
- ベンチ結果Release, 1M/400, PROFILE=C7_SAFE, C7_HOT=1, v2 stats ON:
- C6-heavy min=257/max=768: v2 OFF **42.15M ops/s**、v2 ON(0x40) **29.69M ops/s**。v2 stats cls6 route_hits=0 / free_fb_v1=266930 で実質 v1 経路に落ちており、大幅回帰。
- Mixed 161024B: C7 v2 only (0x80) **45.07M ops/s** かつ cls7 slow_prepare=2276。C6+C7 v2 (0xC0) **35.65M ops/s** まで悪化、cls6 は v1 のままroute_hits=0
- 結論: C6 v2 は初回 A/B で大幅マイナスかつ C6 ルートが実際には v2 を踏んでいない。デフォルトは v2 OFF のまま。C6 v2 は研究箱扱いを継続し、route LUT/冷温境界の見直し・refill 多発の是正が必要。
Phase64: C6 v2 route 修正・C7 v2 refill 再確認
---------------------------------------------
- front の route switch をクラス汎用にし、class6 でも `TINY_ROUTE_HOTHEAP_V2` を通るよう修正。v2 stats に route 値を表示。
- C6-heavy (min=257/max=768, ws=400, iters=100k, classes=0x40): route_hits=26660, alloc_refill=1, fallback_v1=0 → v2 パスが有効化。ただしスループットは **35.5M ops/s** と v1 より低めで要チューニング。
- C7-only 20k/ws=64 v2 ON: alloc_refill=48 / HEAP_STATS slow=48v2 OFF は slow=1。Mixed 20k/ws=256 でも refills≈42。短尺では refill 多発が残るため原因再調査中。長尺 1M/ws=400 では slow=1 のまま。
- `refill_with_current` / `refill_with_partial` のカウンタを追加し、短尺では current/partial が空の状態で refill が発生していることを確認partial/retire は未発火)。当面の運用: デフォルトは v2 OFF。C6 v2 は opt-in 研究箱、C7 v2 は bench/研究プロファイルのみ。
Phase33: C7 v2 ON/OFF A/B現状評価
-----------------------------------
- 条件: C7 SAFE (`PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1`), class mask 0x80, HEAP_STATS=ON。
@ -333,3 +358,109 @@ Phase36 (C7-only Hot Box 暫定実装)
- Cold 境界: `tiny_hotheap_v2_refill_slow``tiny_heap_c7_lease_page_for_v2()` 経由で 1 枚借りる)と `tiny_hotheap_v2_page_retire_slow`返却resetの 2 箇所のみ。Superslab/Tier/Stats は v1 が保持。
- Route/Gate: Route Snapshot に `TINY_ROUTE_HOTHEAP_V2` を設定し、C7 直線パス/汎用パスとも route==v2 のときだけ HotHeap v2 を呼ぶ。その他は v1 → legacy slow へフォールバック。
- 今後: v2 は C7-only bench 用の A/B 前提。Mixed では v2 OFF 推奨。より本格的に進めるなら、v1 依存の lease/pop/push を減らし、Cold Stats Box 経由の更新に寄せる必要がある。
ChatGPT Pro からのフィードバックと v2 ロードマップ
-----------------------------------------------
ChatGPT Pro との設計相談の結果、TinyHeap v2 について以下の整理とロードマップを追加する。
### 1. どこを優先して変えるべきか
- Mixed 161024B の現状:
- HAKMEM ≈ 41M ops/s
- mimalloc ≈ 113M ops/s≒ 2.72.8×
- system ≈ 92M ops/s
- mid/smallmid:
- HAKMEM ≈ 2829M / mimalloc ≈ 54M / system ≈ 15M
- Superslab/OS:
- 1M ops あたりの Superslab OS 呼び出しは数回(`alloc≈2, free≈3, madvise≈2`)。
- page-fault ≈ 6.6k/1M ops はほぼ first-write 起因と推定。
この状態から 7080M (mimalloc の 6070%) を目指すなら、優先度は:
1. TinyHeap v2 を **v1 への依存がない本物の Hot Box** として再設計するA案の強化
2. mid/smallmid/pool v2 はその次の波で攻める(現状でも system より速い)
3. pf/first-touch/HugePage は v3 以降の「最後の 5〜10% を詰める」テーマ
### 2. v1 の上にラッパを乗せるのはやめる
Phase3235 の v2 は「v1 の page を leasepop/push するラッパ」であり、結果として:
- v2 → lease → v1 `tiny_heap_prepare_page` / slow_prepare に落ちる構造
- Mixed で slow_prepare が爆増し、v1 より遅くなるケースが多かった
今後の方針:
- v2 は **「v1 の上に座るラッパ」ではなく、v1 と并列の Hot Box** として扱う。
- Superslab/Tier/Guard/Stats/Learning とは v1/v2 共通の Cold iface を介して話し、v2 から v1 の内部関数を直接叩かない。
### 3. v1/v2 共通の Cold インタフェース (TinyColdIface) の導入
v1 TinyHeapBox / v2 TinyHotHeapBox の両方が、同じ Cold Box 群Superslab/Tier/Guard/Stats/Learningと話すための共通 IF を導入する。
```c
// Hot → Cold (共通インタフェースのイメージ)
typedef struct TinyColdIface {
TinyPageMeta* (*refill_page)(void* cold_ctx, uint32_t class_idx);
void (*retire_page)(void* cold_ctx, TinyPageMeta* page);
} TinyColdIface;
```
- v1:
- 既存 TinyHeapBox の refill/empty 経路を `TinyColdIface` に束ねる。
- v2:
- Hot Box からは `TinyColdIface` 経由で Superslab/Warm/Tier/Stats に触れる。
Cold 側Superslab/Tier/Guard/Statsは、「呼び出し元が v1 か v2 か」を意識せずに済む。
### 4. v1/v2 並立構成Hot Box の二系統)
Box 構造のイメージ:
```text
[Front/Gate Box]
|
+-- if tiny_heap_version[class] == V1 ----> [TinyHeapBox v1]
|
+-- if tiny_heap_version[class] == V2 ----> [TinyHotHeapBox v2]
|
v
[ColdSuperslab/Tier/Stats/Remote/Guard Box]
```
- Front/Gate は `size → class → route` まで決め、その後 `tiny_heap_version[class_idx]` で v1/v2 を選ぶ。
- v1/v2 とも Cold Box とは `TinyColdIface` だけを使う。
- v1 は「安定線safe path」、v2 は「新 Hot Box」として A/B 可能。
### 5. v2 の適用範囲と rollout 方針
- 設計は最初から C5C7 をカバーできるようにする(`TinyHotHeapCtxV2.cls[0..7]` を持つ)。
- rollout は **C7-only → C6 → C5** の順で段階的に:
- PolicySnapshotBox に `tiny_heap_version[class_idx]` を追加V1/V2
- 初期値は `C7 = V1`, C5C6 も V1。
- bench/分析で v2(C7-only) が安定・同等以上になった段階で `C7=V2` に昇格。
- Mixed で問題なければ C6/C5 を順に昇格。
- v1 は常に fallback として残し、`HAKMEM_TINY_HEAP_PROFILE=LEGACY` や専用 ENV で「全クラス v1」に戻せるようにする。
- Phase62 実装メモ:
- C7 v2 に加えて C6 v2 を同じ Hot Box で扱えるようにしたRoute mask bit6/0x40 で opt-in、デフォルト OFF
- Cold IF は v1 をそのままラップする形で、C6/C7 どちらも refill/retire の 2 箇所のみで Superslab/Tier/Stats に触れる。
- ステータス: C7 v2 は Mixed/C7-only で微プラス安定。C6 v2 は実装済みだが bench はこれからbench専用・デフォルトは v1
### 6. v2 のスコープと v3 の線引き
- v2 世代でやること:
- Tiny front/route Box → すでに 1 LUT + 1 switch に整理済み。
- TinyHotHeap v2 を **v1 と并列の Hot Box** として実装し、C5C7 を段階的に移行。
- mid/smallmid/pool は v1 を維持しつつ、v2 の構造スケッチpage-based pool 等)まで設計しておく。
- Superslab/Segment/Tier/Guard/Remote の構造は **変えない**Cold Box を動かさない)。
- v3 以降でやること:
- Superslab/Segment のサイズ・配置・Tier 設計を再定義。
- Tiny と mid/pool を統合した SmallObjectHeap を設計(サイズクラス統合など)。
- Remote/cross-thread free の方式(リモートリスト vs メッセージ vs per-CPUを見直す。
- HugePage/NUMA/first-touch 最適化を本格的に取り入れる。
まとめると:
- v2 は「Hot BoxTinyHeap v2を作り直し、Cold Box はほぼ据え置き」の世代。
- v3 は「Cold BoxSuperslab/Segment/Tierも含めてオブジェクト heap 全体を再構成する」世代。
### 7. Phase65 後半の観測C7 v2 長尺)
- C7-only / Mixed (ws=400, iters=1M) で v2 ON/OFF を再取得したところ、どちらも `slow≈1 / refill≈1` に収束し、性能も v2 ON が微プラスC7-only 38.68M vs OFF 38.24M、Mixed 41.94M vs 41.78M)。
- 短尺 20k で見える refill≈50 はウォームアップ由来と判断。運用デフォルトは v2 OFF のまま研究箱扱いだが、bench では C7 v2 を本命候補として扱える状態。