Phase 36-37: TinyHotHeap v2 HotBox redesign and C7 current_page policy fixes
- Redefine TinyHotHeap v2 as per-thread Hot Box with clear boundaries - Add comprehensive OS statistics tracking for SS allocations - Implement route-based free handling for TinyHeap v2 - Add C6/C7 debugging and statistics improvements - Update documentation with implementation guidelines and analysis - Add new box headers for stats, routing, and front-end management
This commit is contained in:
60
docs/analysis/C6_HOTBOX_DESIGN.md
Normal file
60
docs/analysis/C6_HOTBOX_DESIGN.md
Normal file
@ -0,0 +1,60 @@
|
||||
# C6_HOTBOX_DESIGN
|
||||
|
||||
目的: class6 を C7 SAFE と同じ TinyHeap ベースでホット化するための箱を定義する。まずは SAFE(meta きちんと保持)だけを対象とし、ULTRA(meta を大胆に省く)は C6 ではやらない。
|
||||
|
||||
## 境界(箱の責務)
|
||||
- **内側 (C6 HotBox)**: TinyHeapBox 上での heap → page → block 管理、current_page ポリシー。
|
||||
- **外側 (Cold Box)**: Superslab / Tier / Guard / Stats。TLS SLL とは原則切断(TinyHeap クラスには SLL を使わせない)。
|
||||
|
||||
## ENV / A/B 切替
|
||||
- `HAKMEM_TINY_HEAP_BOX` … TinyHeap front 全体の ON/OFF。
|
||||
- `HAKMEM_TINY_HEAP_CLASSES` … クラスごとの TinyHeap マスク。デフォルトは `0x80` (C7 のみ)。
|
||||
- `HAKMEM_TINY_C6_HOT` … C6 Hot front を有効化するスイッチ(1 で C6 専用直線パスを許可)。
|
||||
- `HAKMEM_TINY_C6_META_MODE` … 0=OFF, 1=SAFE(当面は SAFE のみ。ULTRA はやらない)。
|
||||
- **注意**: meta_mode=1 は現時点では bench/実験専用。長めの C6-heavy でクラッシュする既知事象があり、通常運用は
|
||||
meta_mode=0 または C6 TinyHeap OFF を推奨する。
|
||||
- デバッグ用(meta_mode=1 時の Fail-Fast/可視化):
|
||||
- `HAKMEM_TINY_C6_DEBUG_POP=1` … pop まわりの Fail-Fast を有効化。
|
||||
- `HAKMEM_TINY_C6_DELTA_TRACE=1` … delta を触った箇所を last_delta_site に記録。
|
||||
- `HAKMEM_TINY_C6_DELTA_DEBUG=1` … destructor で delta サマリを dump。
|
||||
- `HAKMEM_TINY_C6_DELTA_TRACE=1` が有効なときは delta サイト (ALLOC/FREE/ATTACH/EMPTY/THRESHOLD) をページに刻み、
|
||||
`HAKMEM_TINY_C6_DEBUG_POP=1` では pop/free の Fail-Fast(範囲外 freelist/ss mismatch/cap0 等)と 512 行までの debug log を出す。
|
||||
|
||||
## 現状の事実(2025-12 時点)
|
||||
- C6 TinyHeap(`HAKMEM_TINY_HEAP_CLASSES=0x40`)は C6-heavy / Mixed どちらも回帰気味(最新測定 2025-12-05)。
|
||||
- C6-heavy (min=257/max=768, ws=256, iters=20k, debug OFF)
|
||||
- LEGACY: **41.74M ops/s**(HEAP_STATS 0)
|
||||
- TinyHeap mode0 (`C6_META_MODE=0`): **36.07M ops/s**(cls6 fast=5381 / slow_prepare=1)
|
||||
- TinyHeap mode1 (`C6_META_MODE=1` SAFE): **28.86M ops/s**(cls6 fast=2692 / slow_prepare=2690)
|
||||
- Mixed 16–1024B (ws=256, iters=20k)
|
||||
- LEGACY: **40.90M ops/s**
|
||||
- C7_SAFE (C6 OFF): **40.96M ops/s**(cls7 fast=5691 / slow=1)
|
||||
- C6+C7 SAFE (`HEAP_CLASSES=0xC0`、両方 meta_mode=1): **27.21M ops/s**(cls6 fast=1388 / slow=1366、cls7 fast=5664 / slow=19)
|
||||
- mode0 は slow_prepare≈1 でも約 -14%(C6-heavy)と大きくマイナス、mode1 は slow_prepare が増えてさらに悪化。現状は bench/実験専用マスク(0x40/0xC0)とし、通常は LEGACY か C7_SAFE のみを推奨。
|
||||
- slow_prepare が小さいまま回帰するため、原因は Front/Hot の命令コストや meta 更新コスト(delta/flush 実装)の重さにあると推定。mode1 は delta/flush を触ることで slow_prepare も増えやすい点に注意。
|
||||
- meta_mode=1 の暫定防御(Phase21–22):
|
||||
- attach で meta->freelist を範囲チェックし、OOB は NULL に潰す。
|
||||
- empty→release で meta->freelist を NULL にし、debug 時は page->free_list に poison。
|
||||
- pop で freelist OOB / ss mismatch / cap0 などを Fail-Fast。
|
||||
- 上記後、C6-heavy iters=1000/1500/2000/20000 で再現していた SIGSEGV は出なくなり、delta サマリは 0/0/0(ただし bench 専用扱いは継続)。
|
||||
|
||||
## 要件と設計方針
|
||||
- 当面は **SAFE のみ**(meta/active を delta + flush で正確寄りに保つ)。ULTRA は C6 では導入しない。
|
||||
- A/B できるように:
|
||||
- C6 Hot front: `HAKMEM_TINY_C6_HOT=1` で直線パスを有効化。
|
||||
- C6 TinyHeap ON/OFF: `HAKMEM_TINY_HEAP_CLASSES` のビットで切替(デフォルトは OFF)。
|
||||
- Box Theory 準拠:
|
||||
- HotBox(TinyHeap 内部)と Cold Box(Superslab/Tier/Guard/Stats)の境界は 1 箇所。
|
||||
- TLS SLL は C6 HotBox からは触らない。
|
||||
|
||||
## 今後のフォーカス
|
||||
- C7 SAFE で効いた current_page 固定+ delta/閾値 flush を C6 に横展開するかを検討。
|
||||
- Front/Hot の命令数を減らすため、C6 専用の直線フロント(Gate → Heap 一本化)を C7 と対称に整える。
|
||||
- 成果の指標:
|
||||
- C6-heavy で LEGACY と同等以上を目指す。
|
||||
- Mixed 16–1024B で C6 を載せてもマイナスが小さい(±1M 以内)こと。
|
||||
|
||||
v1 の結論と凍結方針
|
||||
--------------------
|
||||
- v1 では C6 TinyHeap/Hot はどのモードでも C6-heavy/Mixed で明確なマイナス。meta_mode=1 は bench/実験専用とし、通常は mode0 か OFF を推奨。
|
||||
- C6 の本格的な再設計は TinyHeap v2(C5–C7 をまとめて組み直す箱)で行う。C6 を触るときは bench/実験マスク (0x40/0xC0) とデバッグ ENV を明示的に有効にする。
|
||||
@ -36,6 +36,21 @@ A/B 切替ポリシー(HAKMEM_TINY_C7_HOT)
|
||||
- `HAKMEM_TINY_C7_HOT=1` : C7HotBox を有効化。Gate で `class_idx==7` を検出したときだけ `tiny_c7_alloc_fast` / `tiny_c7_free_fast` を経由する。
|
||||
- `HAKMEM_TINY_C7_HOT=0` : 完全に従来経路へフォールバック(Unified Cache / Warm / Superslab の既存ルート)。
|
||||
- ENV で即時戻せるようにし、Box 境界は slow helper(`tiny_c7_alloc_slow_from_heap` / `tiny_c7_page_becomes_empty`)1 箇所に集約する。
|
||||
- TinyHeap プロファイル: `HAKMEM_TINY_HEAP_PROFILE` を導入(LEGACY/C7_SAFE/C7_ULTRA_BENCH/CUSTOM)。
|
||||
- C7_SAFE: class mask=0x80, C7 meta_mode=1(SAFE)、`HAKMEM_TINY_HEAP_BOX` 自動 ON。C7_HOT は別途 1 を推奨。
|
||||
- C7_ULTRA_BENCH: class mask=0x80, C7 meta_mode=2(bench 専用)。
|
||||
- CUSTOM: 既存の `HAKMEM_TINY_HEAP_CLASSES` / `HAKMEM_TINY_C7_META_MODE` を直接指定。
|
||||
- 推奨セット:
|
||||
- 本番寄せ C7: `HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- C7-only bench: `HAKMEM_TINY_HEAP_PROFILE=C7_ULTRA_BENCH HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- 補足: class6 にも対称の Hot front(`HAKMEM_TINY_C6_HOT` + class mask)を追加済みだが、C6 は回帰が大きく bench/実験専用のまま。
|
||||
- Phase16: Route Snapshot Box (`tiny_route_env_box.h`) を追加し、Gate は「size→class→route LUT→heap/legacy」の 1 分岐構造に整理。C7 SAFE profile でも mixed での回帰を縮めつつ、C7-only は LEGACY≈39.7M / SAFE≈41.1M / ULTRA≈46.1M (20k/ws=64, Release, LARSON_FIX=1)。
|
||||
|
||||
現状の位置づけ (Phase 19)
|
||||
--------------------------
|
||||
- C7 SAFE: C7-only 20k/ws64 ≈46.6M ops/s、Mixed 16–1024B は LEGACY と ±1M 以内。C7-heavy で推奨。
|
||||
- C7 ULTRA_BENCH: C7-only 20k/ws64 ≈52M(bench 専用、Superslab/Tier 統計は緩むため本番では OFF)。
|
||||
- C6 TinyHeap: C6-heavy / Mixed で throughput が明確に悪化(例: LEGACY≈44.3M → C6 TinyHeap≈38.6M)。`HAKMEM_TINY_HEAP_CLASSES=0x40/0xC0` は bench/実験専用マスクとして扱う。
|
||||
|
||||
メモ
|
||||
----
|
||||
@ -119,6 +134,52 @@ Phase 9: Tiny lane 判定を TinyHeap と揃える
|
||||
- Mixed 16–1024B: OFF≈47.6M / C7 only TinyHeap≈36.9M / C6+C7 TinyHeap≈30.3M(警告なし)。
|
||||
- 依然として性能は TinyHeap OFF より低いケースがあるため、C6/C7 の slow_prepare 削減や current_page 利用強化を次フェーズで行う。
|
||||
|
||||
Phase ULTRA: C7 meta モードの三段化(bench 専用 ULTRA 追加)
|
||||
------------------------------------------------------------
|
||||
- ENV `HAKMEM_TINY_C7_META_MODE` を追加(0:OFF, 1:SAFE meta-light=従来の delta+閾値 flush/clamp, 2:ULTRA)。未指定時は `HAKMEM_TINY_C7_META_LIGHT` を後方互換ゲートとして扱い SAFE=1 相当。
|
||||
- ULTRA(mode=2) は C7-only ベンチ専用。per-alloc で meta->used / ss_active_* を一切更新せず、delta/flush もスキップする高速モード。2024-xx-xx 時点で pop/push の meta->freelist/carved atomic も省略し、ベンチ専用の最小オーバーヘッド構成にしている(Box 境界は維持しつつ Superslab/Tier の統計整合は犠牲にする)。
|
||||
- SAFE(mode=1) はこれまでのページ境界 flush + 閾値 flush + attach clamp を維持し、本番で使うなら mode=0/1。ULTRA は「bench/研究用途のみ」と明記。
|
||||
- C7-only 20k/ws=64 (Release, HEAP_BOX=1, HEAP_CLASSES=0x80, HOT=1, LARSON_FIX=1):
|
||||
- mode=0: ≈38.7M ops/s(alloc_fast_current=10052 / alloc_slow_prepare=7681)
|
||||
- mode=1: ≈34.1M ops/s(alloc_fast_current=5837 / alloc_slow_prepare=5179)
|
||||
- mode=2: ≈41.6M ops/s(alloc_fast_current=5948 / alloc_slow_prepare=5068)
|
||||
- current_page 可視化(Phase 11): `g_c7_page_stats` を追加し、prepare_calls / prepare_with_current_null / prepare_from_partial / current_set_from_free / current_dropped_to_partial を `HAKMEM_TINY_C7_HEAP_STATS=1` でダンプ。C7-only ULTRA (20k/ws=64) では `prepare_with_current_null=prepare_calls` となり、free 側で current_page を保持できていないことが見えたため、current 固定化ポリシーを継続検討中。
|
||||
- current 固定化の初期版(ULTRA 専用): empty/full での unlink を避け、free 後は常に current_page に据え置く + prepare で current を優先するように変更。C7-only 20k/ws=64 (mode=2) で ops≈52.0M、alloc_fast_current=11015 / alloc_slow_prepare=1 / prepare_calls=1 まで改善。SAFE への逆輸入は未定(ULTRA は bench 限定)。
|
||||
- SAFE (mode=1) への current ポリシー逆輸入 (Phase 12):
|
||||
- free で used>0 の page を current に据え直し、empty でも delta flush のみで detach/publish を避けて current を保持。mark_full でも C7 meta_light が current を指す場合は unlink しない。
|
||||
- prepare_page も C7 meta_light で current に空きがあれば即 return(refill へ降りない)。
|
||||
- ベンチ (C7-only, ws=64, HEAP_BOX=1, HEAP_CLASSES=0x80, HOT=1, LARSON_FIX=1): SAFE mode=1 20k ≈46.6M ops/s(alloc_fast_current=11015 / alloc_slow_prepare=1 / free_fast_local=8726, prepare_calls=1)。長時間 100k≈46.7M / 200k≈44.99M、`HAKMEM_TINY_C7_DELTA_DEBUG=1` でも delta 残 0 を確認。
|
||||
- ULTRA(mode=2) は bench 専用のまま。本番寄り構成は mode=0/1 を推奨。
|
||||
|
||||
Phase 13: mixed での SAFE 効果と multi-class stats
|
||||
---------------------------------------------------
|
||||
- Stats を `TinyHeapClassStats[]` に拡張(ENV: `HAKMEM_TINY_HEAP_STATS` / `_DUMP`、旧 `_C7_` 互換)し、C6/C7 の fast/slow/fallback を同時に計測可能にした。
|
||||
- Mixed 16–1024B (iters=20k, ws=256, LARSON_FIX=1):
|
||||
- TinyHeap OFF: ≈43.7M ops/s。
|
||||
- C7 SAFE のみ TinyHeap (`HEAP_BOX=1 HEAP_CLASSES=0x80 META_MODE=1 HOT=1`): ≈44.9M ops/s(`HEAP_STATS[7] fast=5691 slow_prepare=1`)。
|
||||
- C6+C7 TinyHeap (`HEAP_CLASSES=0xC0`): ≈39.3M ops/s(`HEAP_STATS[6] fast=2744 slow=1`, `HEAP_STATS[7] fast=5691 slow=1`)。
|
||||
- C6 偏重 (min=257 max=768):
|
||||
- TinyHeap OFF: ≈43.8M ops/s。
|
||||
- C6 TinyHeap のみ: ≈38.5M ops/s(`HEAP_STATS[6] fast=5372 slow=1`)。
|
||||
- C6+C7 TinyHeap: ≈40.6M ops/s(`HEAP_STATS[6] fast=5372 slow=1`, `HEAP_STATS[7] fast=5691 slow=1`)。
|
||||
- 方針: C7 SAFE は mixed でも悪化せず、C7-only では legacy 超え → デフォルト TinyHeap 候補。C6 は slow_prepare 自体は少ないが経路オーバーヘッドで低下するため、当面は bench/実験用 (HEAP_CLASSES=0x40/0xC0)。C7-only を突き抜けるベンチは ULTRA (META_MODE=2) を手動で使う。
|
||||
|
||||
Phase 17: C7 フロント超直線化(HotPipeline 前倒し)
|
||||
----------------------------------------------------
|
||||
- Route Snapshot を使った C7 判定ヘルパ `tiny_c7_front_uses_heap()` を追加。Gate から class7 が TinyHeap 経路かどうかを 1 LUT で判定できるようにした。
|
||||
- `malloc_tiny_fast` の冒頭に「size==1024 かつ C7 route=HEAP」専用パスを追加。クラス判定/LUT/route を飛ばして `tiny_c7_alloc_fast` へ直行し、miss 時だけ Legacy Tiny slow (`tiny_cold_refill_and_alloc(7)`) に静かにフォールバック。
|
||||
- `free_tiny_fast` も C7 route=HEAP を先に評価し、Larson fix ブロックの owner 判定後に `tiny_c7_free_fast_with_meta` へ直行する経路を明示(route はスナップショットから 1 回だけ読む)。
|
||||
- ベンチ (Release, iters=20k, ws=64, LARSON_FIX=1, HOT=1):
|
||||
- C7-only: PROFILE=LEGACY ≈37.1M / C7_SAFE ≈38.2M / C7_ULTRA_BENCH ≈45.3M ops/s。
|
||||
- Mixed 16–1024B (ws=256): PROFILE=LEGACY ≈40.3M / C7_SAFE ≈40.7M ops/s(差 ~-1M まで縮小)。
|
||||
- 今後の選択肢メモ: (A) C6 TinyHeap を C7 SAFE 流(current 固定+meta-light SAFE)に寄せるか、(B) Tiny front/gate/UC の命令削減を perf で詰めるかを次フェーズで決める。
|
||||
|
||||
Phase 18 メモ(C6 SAFE 実験とプロファイル整理)
|
||||
------------------------------------------------
|
||||
- TinyHeap プロファイル箱に加え、`HAKMEM_TINY_C6_META_MODE`(0/1)を追加。現状の C6 SAFE は整合優先で挙動は mode 0 相当(delta/flush 未使用、meta/active は per-alloc 更新)だが、クラスマスクで C6 を TinyHeap に載せたまま A/B 計測できる。
|
||||
- C6 偏重 20k/ws=256 では LEGACY ≈44.3M → C6 TinyHeap (mask=0x40, META_MODE=0/1) ≈38.6〜38.8M、C6+C7 TinyHeap (0xC0, META_MODE=1) ≈39.9M。Mixed 16–1024B でも C6 TinyHeap は ≈38.5〜38.7M、C6+C7 TinyHeap ≈39.5M(slow_prepare はいずれも ≈1 と低い)。
|
||||
- デフォルト profile は引き続き C7 SAFE / C7 ULTRA_BENCH / LEGACY の 3 択。C6 を TinyHeap に載せるのは bench/研究用(クラスマスク 0x40/0xC0 を明示)とし、本番では 0x80=C7 のみを推奨。C6 向け meta-light を安全に再導入する場合は Superslab 解放まわりの安全性を再確認する。
|
||||
|
||||
TinyHeapBox への載せ替え(Phase 1.0 構造)
|
||||
------------------------------------------
|
||||
- C7HotBox の実体を `core/box/tiny_heap_box.h` の汎用 TinyHeapBox 上に配置し、型は `tiny_heap_ctx_t` / `tiny_heap_page_t` へ統一。
|
||||
|
||||
74
docs/analysis/COLD_TINY_STATS_BOX_DESIGN.md
Normal file
74
docs/analysis/COLD_TINY_STATS_BOX_DESIGN.md
Normal file
@ -0,0 +1,74 @@
|
||||
Cold Tiny Stats Box (初期メモ)
|
||||
=============================
|
||||
|
||||
目的
|
||||
----
|
||||
- Tiny のホットパス (TinyHeap/Front) では「page->used の増減だけ」に集中し、Superslab/Tier/Guard 用の meta->used / ss_active_* / 学習系カウンタの更新は Cold 側に押し出す。
|
||||
- C7 SAFE で導入した page 内 delta + flush を一般化し、「Stats Box」がイベントを受け取って統計を更新する構造に寄せる。
|
||||
|
||||
境界の考え方
|
||||
------------
|
||||
- Hot 側 (TinyHeap / TinyFront / HotBox):
|
||||
- やること: page->used の増減、必要なら「EVENT_ALLOC / EVENT_FREE」などの軽い通知を 1 回投げるだけ。
|
||||
- やらないこと: meta->used / ss_active_* / Tier 判定用カウンタを直接いじる。
|
||||
- Cold Stats Box 側:
|
||||
- Hot からのイベントをバッファ or 簡易カウンタで受け取り、
|
||||
- Superslab/Tier/Guard が参照する統計値に反映する(当面は flush 境界で即時更新。次フェーズでバッチ化を検討)。
|
||||
|
||||
C7 SAFE との関係
|
||||
----------------
|
||||
- C7 SAFE ではすでに page 内に used_delta/active_delta を持ち、empty/threshold/attach 時に flush して meta/active を更新する「ミニ Aggregator」がある。
|
||||
- 本フェーズ以降は「flush 部分だけを Stats Box に委譲」→「Stats Box で pending に貯め、所定のトリガでまとめて meta/active を反映」という二段構えに進化させる。
|
||||
- 将来的には Stats Box 内で本格的なバッチ更新・学習カウンタ更新を担う余地を残す。
|
||||
|
||||
遅延の許容と不変条件(C7 基準)
|
||||
--------------------------------
|
||||
- Superslab/Tier/Guard が前提にする不変条件:
|
||||
- meta->used / ss_active_* は「ページが Superslab を離れる前」に必ず整合した値に戻っていること。
|
||||
- Tier 判定や Guard/OOM 判定は「一時的に +α(最大 K ページぶん)」までなら許容するが、K は環境から明示的に決める。
|
||||
- 今回の方針:
|
||||
- 1 ページあたり最大「capacity×16」程度までの pending なら遅延を許容(ENV で ON のときのみ)。
|
||||
- ページが empty になり Superslab/Tier に返る直前、または pending が閾値を超えたときに必ず flush。
|
||||
- Superslab を完全 release する前に pending=0 になる(empty で flush を強制する)ため、Tier/Guard の破綻は避ける。
|
||||
|
||||
ENV / A/B ポリシー
|
||||
------------------
|
||||
- HAKMEM_TINY_STATS_BOX=0/1 で Stats Box 経由を切替。
|
||||
- 0: これまで通り TinyHeap 内で meta/active を直接更新。
|
||||
- 1: C7 SAFE の flush を Stats Box 経由に分離。
|
||||
- HAKMEM_TINY_STATS_BATCH=0/1 で meta/active の適用タイミングを切替(Stats Box が有効な場合のみ有効)。
|
||||
- 0: flush ごとに即 meta->used / ss_active_* を更新(従来挙動)。
|
||||
- 1: flush で得た delta を page pending に貯め、閾値/empty/release/destructor でまとめて反映。
|
||||
- 当面は C7 のみ対象。他クラスや C6 への適用は次フェーズ以降の検討事項。
|
||||
|
||||
初期 A/B(C7-only 20k/ws=64, PROFILE=C7_SAFE, HOT=1, HEAP_STATS=ON)
|
||||
--------------------------------------------------------------------
|
||||
- STATS_BOX=0: 42.99M ops/s(cls7 fast=11015 / slow=1)
|
||||
- STATS_BOX=1: 42.92M ops/s(cls7 fast=11015 / slow=1)
|
||||
- いずれも delta summary=0 で挙動差なし(場所だけ Box に分離)。
|
||||
|
||||
今フェーズの実装(概要)
|
||||
-------------------------
|
||||
- Stats Box に page 単位の pending(used_delta/active_delta) を追加。
|
||||
- C7 SAFE の flush は「delta を Stats Box に渡すだけ」に変更し、Stats Box が
|
||||
- STATS_BATCH=0: 即座に meta/active 更新。
|
||||
- STATS_BATCH=1: pending に加算し、閾値超え/empty でまとめて meta/active へ反映。
|
||||
- Hot 側(TinyHeap/C7 SAFE)のコード量は変えず、Cold 側だけで更新タイミングを差し替えられる形にした。
|
||||
|
||||
Phase27 A/B(バッチ有効時の影響)
|
||||
---------------------------------
|
||||
- C7-only 20k/ws=64(PROFILE=C7_SAFE, HOT=1, LARSON_FIX=1, HEAP_STATS=ON)
|
||||
- STATS_BOX=0: 43.31M ops/s
|
||||
- STATS_BOX=1, BATCH=0: 43.06M ops/s(fast/slow 同一)
|
||||
- STATS_BOX=1, BATCH=1: 35.10M ops/s(大幅マイナス)
|
||||
- STATS_BOX=1, BATCH=1, META_MODE=2(ULTRA bench): 48.55M ops/s
|
||||
- Mixed 16–1024B 20k/ws=256
|
||||
- LEGACY: 40.92M ops/s
|
||||
- C7_SAFE + STATS_BOX=1, BATCH=0: 42.72M ops/s
|
||||
- C7_SAFE + STATS_BOX=1, BATCH=1: 35.27M ops/s
|
||||
- 判断: BATCH=1 は C7-only/Mixed とも大きく劣化。bench 専用に留め、標準は STATS_BOX=1 & BATCH=0(または STATS_BOX=0)とする。
|
||||
|
||||
標準設定 (v1)
|
||||
--------------
|
||||
- 推奨: PROFILE=C7_SAFE 時は `HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0` を標準とし、レガシー比較時は STATS_BOX=0 でも可。
|
||||
- Bench/実験: `HAKMEM_TINY_STATS_BATCH=1` は bench 専用(C7-only/Mixed とも大幅マイナス)。C7_ULTRA_BENCH で試すときのみ併用を許容。
|
||||
31
docs/analysis/FINAL_PERF_STATUS_2025XX.md
Normal file
31
docs/analysis/FINAL_PERF_STATUS_2025XX.md
Normal file
@ -0,0 +1,31 @@
|
||||
# FINAL_PERF_STATUS_2025XX
|
||||
|
||||
箱理論で進めた v1 系の最終スナップショット。ベスト構成と残差、次の大きなテーマを一枚にまとめる。
|
||||
|
||||
## ベスト構成(デフォルト想定)
|
||||
- Tiny: `HAKMEM_TINY_HEAP_PROFILE=C7_SAFE`, `HAKMEM_TINY_HOTHEAP_V2=0`, `HAKMEM_TINY_STATS_BOX=1`, `HAKMEM_TINY_STATS_BATCH=0`, `HAKMEM_TINY_LARSON_FIX=1`
|
||||
- Pool: `HAKMEM_POOL_V2_ENABLED=0`(回帰防止のため v1 を標準)
|
||||
- HugePage/ヘッダ-light/実験系: すべて OFF(研究箱扱い)
|
||||
|
||||
## 性能一覧(リリースビルド、代表プロファイル)
|
||||
- C7-only (ws=64, iters=20k): ≈40.6M ops/s
|
||||
- mimic/system との差: mimalloc ≈112.9M, system ≈92.1M → HAKMEM は mimic の ~36%、system の ~44%
|
||||
- Mixed 16–1024B (ws=256, iters=20k): ≈38–39M ops/s(v2 OFF, C7_SAFE)
|
||||
- mimalloc/system は未計測同条件だが C7-only 比率から推定し ~40% 前後
|
||||
- mid/smallmid (bench_mid_large_mt_hakmem 1 1,000,000 400 1, v2 OFF): ≈27.4–28.4M ops/s
|
||||
- mimalloc ≈54.2M → HAKMEM は ~50% 近辺
|
||||
|
||||
## 埋めた「大きな穴」
|
||||
- Tiny front/route フラット化(size→class→route→alloc/free を 1 LUT+switch に縮約)
|
||||
- Warm Pool / Superslab OS stats で pf/sys の大穴を特定し、OS alloc/free はほぼゼロ化
|
||||
- SS_OS_STATS/Cold Stats Box で Superslab⇔OS/Stats を可視化し、デフォルトは A/B で安全側
|
||||
- C7 SAFE TinyHeap を標準に固定(v2 は研究箱)。Tiny v2 は完全ゲート付きでデフォルト OFF
|
||||
- Pool v1/v2 ゲート追加:`HAKMEM_POOL_V2_ENABLED=0` を標準にし、回帰を即切り戻せるようにした
|
||||
|
||||
## ここから先(v3 テーマ候補)
|
||||
- TinyHeap v2 をゼロから設計(C5–C7 を統合する HotHeap、現在の実験 v2 とは別物)
|
||||
- First-touch / header-light / HugePage の本格対応(bench 専用から昇格させるか検証)
|
||||
- mid/smallmid の pool 系さらなる軽量化 or 別フロント
|
||||
- Tiny front 以外(mid/large)での route フラット化・命令数削減
|
||||
|
||||
備考: v2 系・ヘッダ light・HugePage はすべて「明示的に ENV を立てた研究モード」のまま据え置き。標準ベンチ/比較は上記ベスト構成で見る。***
|
||||
51
docs/analysis/FIRST_TOUCH_PAGEFAULT_REDUCTION_PLAN.md
Normal file
51
docs/analysis/FIRST_TOUCH_PAGEFAULT_REDUCTION_PLAN.md
Normal file
@ -0,0 +1,51 @@
|
||||
# FIRST_TOUCH_PAGEFAULT_REDUCTION_PLAN
|
||||
|
||||
## 現状サマリ(基準プロファイル: 16–1024B, ws=400, iters=1M, C7_SAFE, v2 OFF)
|
||||
- HAKMEM: ~6,600 page-faults / ~40.6M ops/s, user≈29 ms / sys≈18.5 ms
|
||||
- mimalloc: ~150 page-faults / ~112.9M ops/s
|
||||
- system malloc: ~130 page-faults / ~92.1M ops/s
|
||||
- Superslab OS 呼び出し(HAKMEM_SS_OS_STATS=1): alloc=2 / free=3 / madvise=2 → OS mmap/munmap は支配的でない
|
||||
- WarmPool (C7): ヒット ~99% でほぼ効いている。残存 pf は first-write が主因と推定。
|
||||
|
||||
## 方針(研究用 / デフォルト OFF)
|
||||
- Mode A: Superslab を HugePage / 大きめサイズで確保し、first-write そのものを減らす実験
|
||||
- Mode B: allocator 側の初期書き込み(ヘッダ/ゼロ埋め)を減らし、first-touch をアプリ側に寄せる実験
|
||||
- いずれも ENV で opt-in。デフォルトは OFF(本番プロファイルは現状維持)。
|
||||
|
||||
## Mode A: HugePage / 大きめ Superslab 実験 Box(実験実装済み)
|
||||
- Box 案: SuperSlabHugePageBox(Cold 側で実験用)
|
||||
- ENV:
|
||||
- `HAKMEM_SS_HUGEPAGE_EXPERIMENT=1` で HugePage を試行(デフォルト 0)
|
||||
- `HAKMEM_SS_HUGEPAGE_SIZE` でページサイズ指定(未指定なら 2MB を仮定)
|
||||
- 実装(Phase52):
|
||||
- ss_os_acquire が ENV ON のときだけ `MAP_HUGETLB`(`MAP_HUGE_2MB` も併用できる環境では付与)を試し、失敗時は静かに通常 mmap にフォールバック。Stats で huge_alloc / huge_fail を出力。
|
||||
- Superslab サイズが 2MB と一致するときのみ HugePage を試す(その他サイズは従来経路)。
|
||||
|
||||
## Mode B: allocator 側 first-write 削減案
|
||||
- ヘッダ書き込みを減らすオプション(C5/C6/C7 region_id/guard ヘッダを実験的に省略)。安全性とトレードオフなので研究用 BOX (FirstTouchPolicyBox) に閉じ込める。
|
||||
- ゼロ初期化の重複を洗う:
|
||||
- どこで memset/clear をしているか(Tiny front / mid / Superslab)を列挙し、アプリが必ず書く領域を allocator 側で二重初期化していないか確認。
|
||||
- Box Theory ルール:
|
||||
- ポリシーは FirstTouchPolicyBox に集約し、ホットパスは policy snapshot を読むだけにする。
|
||||
- Tiny ヘッダ/初期化の 3 モード(bench 専用 ENV 実装済み):
|
||||
- `full`(デフォルト): region_id_write_header を常に書き戻す(従来どおり)。
|
||||
- `light`: 既存ヘッダと一致する場合は再書き込みを避け、必要最小限だけ書く。
|
||||
- `off`(bench 専用): 既存ヘッダが正しければ書かず、壊れているときだけ最小限を書き戻す(free の整合性確保のための最低限)。guard/memset もスキップ。
|
||||
- ENV: `HAKMEM_TINY_HEADER_MODE=full|light|off`(未指定は full)。旧 `HAKMEM_TINY_WRITE_HEADER=0` は `off` 相当として互換維持。
|
||||
- 実験結果(Mixed 16–1024B, ws=400, iters=1M, C7_SAFE, v2 OFF):
|
||||
- HEADER_MODE=full: ≈42.40M ops/s, page-faults ≈6,662, cycles ≈176M。
|
||||
- HEADER_MODE=light: ≈38.75M ops/s, page-faults ≈6,661, cycles ≈187M。
|
||||
- HEADER_MODE=off: ≈39.33M ops/s, page-faults ≈6,662, cycles ≈184M。
|
||||
- 所感:
|
||||
- pf 回数は 3 モードとも ≈6.66k でほぼ同一。ヘッダ write 軽量化では first-touch page-fault は減らない。
|
||||
- cycles/ops は full が最良で、light/off は判定・分岐コストの増加により約 7〜9% の性能低下。
|
||||
- 現時点では運用デフォルトは full のままが最良。light/off は bench 専用の research モードとして維持し、本番プロファイルでは使用しない。
|
||||
|
||||
## 評価プロファイル(pf/sys A/B 用に固定)
|
||||
- プロファイル: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- メトリクス: ops/s, page-faults, user/sys(perf stat: cycles,instructions,task-clock,page-faults)
|
||||
- このプロファイルで Mode A/B を A/B し、pf がどこまで下がるかを見る。
|
||||
|
||||
## ガードレール
|
||||
- HugePage / header-skip / zero-skip は研究専用でデフォルト OFF。ENV 明示なしでは有効化しない。
|
||||
- 本番プロファイルに入れる場合は Fail-Fast / Guard(明示 opt-in)と長時間安定性テストを必須にする。
|
||||
46
docs/analysis/MID_LARGE_CPU_HOTPATH_ANALYSIS.md
Normal file
46
docs/analysis/MID_LARGE_CPU_HOTPATH_ANALYSIS.md
Normal file
@ -0,0 +1,46 @@
|
||||
# MID/Large CPU Hotpath (Phase54)
|
||||
|
||||
- 条件: `./bench_mid_large_mt_hakmem 1 1000000 400 1` (Release)
|
||||
`HAKMEM_TINY_HEAP_PROFILE=C7_SAFE`, `HAKMEM_TINY_C7_HOT=1`, `HAKMEM_TINY_HOTHEAP_V2=0`, `HAKMEM_TINY_LARSON_FIX=1`
|
||||
- スループット: HAKMEM ≈28.1M ops/s(mimalloc 54.2M / system 15.3M は Phase53 より)
|
||||
- perf stat (cycles:u): IPC≈2.4、page-faults≈7.4k(Phase53 と同等)
|
||||
|
||||
## cycles:u ホットシンボル(self%)
|
||||
- hak_pool_try_alloc.part.0 … 14.7% (pool alloc ホットパス)
|
||||
- worker_run … 9.2% (ドライバ側のループと malloc 呼び出しを含む)
|
||||
- free / hak_free_at.constprop.0 … ~9–10%(glibc free 連携+自前 free)
|
||||
- __memset_avx2_unaligned_erms … ~9%(pool 初期化/clear と推定)
|
||||
- mid_desc_lookup … 3.8%
|
||||
- hak_super_lookup … 1.4%
|
||||
- hak_pool_free.part.0 … 0.7%
|
||||
|
||||
## 所感
|
||||
- pool 系(hak_pool_try_alloc / hak_pool_free)と free/memset が支配的で、mid_desc_lookup と super_lookup も目立つ。
|
||||
- kernel 枠の大きな inclusive% は free/memset 配下にぶら下がっており、userland 側の pool/front の命令数削減が効果的そう。
|
||||
|
||||
## Phase55 方針(pool allocator ホットパス軽量化)
|
||||
- スコープ: core/hakmem_pool.c / core/hakmem_smallmid.c / core/box/pool_* の pool fast path。
|
||||
- hak_pool_try_alloc を直線化:
|
||||
- 「TLS/local freelist hitなら即 return」を先頭に寄せ、debug/統計/slow は unlikely 側へ。
|
||||
- mid_desc_lookup/クラス情報は入口で 1 回だけ計算し、TLS へのキャッシュを検討。
|
||||
- hak_pool_free / hak_free_at:
|
||||
- self-thread free は pool push を最優先にし、cross-thread/debug は unlikely に寄せる。
|
||||
- free 時の memset/初期化が不要なケースを洗い出し、スキップ余地をメモ。
|
||||
- mid_desc_lookup のキャッシュ:
|
||||
- size→class→desc を入口で 1 回だけ決める仕組み(既存キャッシュの再利用も含め)を検討。
|
||||
- 成功ライン(bench_mid_large_mt_hakmem 1 1000000 400 1, Release):
|
||||
- ops/s を 28–29M → 30–32M(+5〜10%)へ。
|
||||
- perf report で hak_pool_try_alloc + free 周辺 self% が数ポイント低下。
|
||||
|
||||
## Phase56 結果(pool fast path 初期実装)
|
||||
- 変更: PoolBlock→user 変換をヘルパに寄せ、TLS ring/lo pop と self-thread free push を直線化。owner 判定は mid_desc の 1 回 lookup で共有。
|
||||
- ベンチ(C6-heavy, ws=256, iters=20k, C7_SAFE, v2 OFF): **25.9M ops/s**(目標 30–32M に届かず、前回 28–29M から回帰)。
|
||||
- perf stat(同条件 1M/400): cycles=225,766,496、instructions=528,335,613、task-clock=57.88ms、ops/s≈25.7M。
|
||||
- 所感: fast-path整理だけでは効果薄く、むしろ低下。pool 内の memset/desc まわりやリング補充順序をより大胆に削らないと改善しない。次のステップとして追加の枝削減・キャッシュ導入を検討。
|
||||
|
||||
## Phase57 回帰トリアージ(pool v2 をゲート化)
|
||||
- 変更: `HAKMEM_POOL_V2_ENABLED` を追加し、v1/v2 の pool 実装を env で切替。細分スイッチとして `HAKMEM_POOL_V2_BLOCK_TO_USER` / `HAKMEM_POOL_V2_TLS_FAST_PATH` を用意(デフォルト ON, v2 時のみ有効)。
|
||||
- ベンチ(C6-heavy, 1M/400, Release):
|
||||
- v1 (POOL_V2_ENABLED=0): **27.40M ops/s**
|
||||
- v2 (POOL_V2_ENABLED=1): **24.73M ops/s**
|
||||
- 所感: v2 の変更が回帰要因と判明。標準は v1 に戻し、スイッチ単位の A/B でどの改変が悪いかを切り分ける方針。
|
||||
29
docs/analysis/PERF_ANALYSIS_MID_LARGE_PHASE53.md
Normal file
29
docs/analysis/PERF_ANALYSIS_MID_LARGE_PHASE53.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Phase53: Mid/Smallmid ベンチ簡易計測(シングルスレッド)
|
||||
|
||||
- 条件: 1 thread / cycles=1,000,000 / ws=400 / reps=1
|
||||
- ビルド: `make bench_mid_large_mt_hakmem bench_mid_large_mt_mi bench_mid_large_mt_system -j4`
|
||||
- プロファイル: TinyHotHeap v2 OFF、C7_SAFE プロファイル、LARSON_FIX=1、その他デフォルト
|
||||
|
||||
## スループット比較
|
||||
|
||||
- HAKMEM: `./bench_mid_large_mt_hakmem 1 1000000 400 1` → **28.43M ops/s**(別 run perf 時 29.02M)
|
||||
- mimalloc: `./bench_mid_large_mt_mi 1 1000000 400 1` → **54.22M ops/s**
|
||||
- system malloc: `./bench_mid_large_mt_system 1 1000000 400 1` → **15.29M ops/s**
|
||||
|
||||
## perf stat (HAKMEM, user+sys)
|
||||
|
||||
- コマンド: `perf stat -e cycles,instructions,task-clock,page-faults ./bench_mid_large_mt_hakmem 1 1000000 400 1`
|
||||
- 結果:
|
||||
- cycles: 211,394,722
|
||||
- instructions: 513,342,673 (IPC ≈ 2.43)
|
||||
- task-clock: 57.48 ms (user 33.29 ms / sys 25.22 ms)
|
||||
- page-faults: 7,374
|
||||
- スループット: 29.02M ops/s(計測 run の値)
|
||||
|
||||
## 所感 / 次の判断材料
|
||||
|
||||
- mid/smallmid (257–768B主体) では mimalloc が HAKMEM の約 1.9×。system はさらに低い。
|
||||
- page-faults は 7.3k と Tiny (16–1024B) よりやや多めだが、主因は CPU 側命令量と sys 部分の比率。
|
||||
- 次の選択肢:
|
||||
- mid/smallmid パス(Tiny 以外)のホットパスを狙う箱
|
||||
- もしくは Tiny 側での残り課題と比較して優先度を決める材料に。
|
||||
205
docs/analysis/PERF_ANALYSIS_TINY_FRONT_FLATTEN_PHASE42.md
Normal file
205
docs/analysis/PERF_ANALYSIS_TINY_FRONT_FLATTEN_PHASE42.md
Normal file
@ -0,0 +1,205 @@
|
||||
# Phase42 Front Route Flatten ベースライン計測
|
||||
|
||||
- ビルド: `make bench_random_mixed_hakmem -j4`
|
||||
|
||||
## C7-only (ws=64, iters=20000, v2 OFF)
|
||||
- ENV: `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- 結果: `Throughput = 41365988 ops/s`
|
||||
- 備考: HEAP_STATS のダンプは出ず(要調査)。FRONT_CLASS: cls7 alloc=11016。
|
||||
|
||||
## Mixed 16–1024B (ws=256, iters=20000, v2 OFF)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- 結果: `Throughput = 43538552 ops/s`
|
||||
- 備考: FRONT_CLASS alloc counts(cls2:147, cls3:341, cls4:720, cls5:1420, cls6:2745, cls7:5692)。HEAP_STATS ダンプは出ず。
|
||||
|
||||
## Tiny-only 8–128B (ws=256, iters=20000, v2 OFF) ※任意測定
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=8 HAKMEM_BENCH_MAX_SIZE=128 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- 結果: `Throughput = 65979164 ops/s`
|
||||
- 備考: FRONT_CLASS alloc counts(cls2:147, cls3:341, cls4:720, cls5:9857)。HEAP_STATS ダンプは出ず。
|
||||
|
||||
---
|
||||
|
||||
# Phase43 (HEAP_STATS 再有効化の再計測) ※v2 OFF
|
||||
|
||||
- HEAP_STATS 用 ENV を明示 (`HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1`) したが、現状はダンプが出ていない。fast/slow の値は別途要確認。
|
||||
|
||||
## C7-only (ws=64, iters=20000)
|
||||
- ENV: `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- Throughput: `37,777,547 ops/s`
|
||||
- HEAP_STATS cls7: fast=11015 slow=1 / free_fast_local=8726、C7_PAGE_STATS: prepare_calls=1 prepare_with_current_null=1
|
||||
- FRONT_CLASS: cls7 alloc=11016 free=8726
|
||||
|
||||
## Mixed 16–1024B (ws=256, iters=20000)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- Throughput: `42,029,698 ops/s`
|
||||
- HEAP_STATS cls7: fast=5691 slow=1 / free_fast_local=4573(cls5/6 未出力)
|
||||
- FRONT_CLASS alloc: cls2=147 cls3=341 cls4=720 cls5=1420 cls6=2745 cls7=5692
|
||||
|
||||
## Tiny-only 8–128B (ws=256, iters=20000)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=8 HAKMEM_BENCH_MAX_SIZE=128 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- Throughput: `65,890,043 ops/s`
|
||||
- HEAP_STATS: 出力なし(cls7 も 0)→ クラス0〜6は計測対象外の可能性。要調査。
|
||||
|
||||
### メモ
|
||||
- C7-only では HEAP_STATS/PAGE_STATS が出ることを確認。Mixed/Tiny-only では cls7 以外の HEAP_STATS が落ちておらず、環境/計測対象の条件を再確認する余地あり。
|
||||
|
||||
# Phase43'': 計測専用で C6/C7 を TinyHeap に載せた場合(v2 OFF)
|
||||
|
||||
## Mixed 16–1024B (ws=256, iters=20000, class mask=0xC0, C6+C7)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HEAP_CLASSES=0xC0 HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_C6_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- Throughput: `32,227,500 ops/s`(性能は大幅に低下、計測専用)
|
||||
- HEAP_STATS:
|
||||
- cls6: fast=2744 slow=1 free_fast_local=2745
|
||||
- cls7: fast=5691 slow=1 free_fast_local=4572
|
||||
- FRONT_CLASS alloc: cls2=147 cls3=341 cls4=720 cls5=1420 cls6=2745 cls7=5692
|
||||
|
||||
## Tiny-only 8–128B (ws=256, iters=20000, class mask=0xC0, C6+C7)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=8 HAKMEM_BENCH_MAX_SIZE=128 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HEAP_CLASSES=0xC0 HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_C6_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1 HAKMEM_TINY_FRONT_CLASS_STATS=1`
|
||||
- Throughput: `63,341,251 ops/s`
|
||||
- HEAP_STATS: 出力なし(対象クラスが 5 未満中心のため?)
|
||||
|
||||
### 所感
|
||||
- C6 を TinyHeap 経由にすると Mixed で大きくマイナス(32M)。cls6/7 の slow はいずれも 1 なので、性能低下はフロント/ホットパスの命令数増が主因と見られる。
|
||||
- 計測目的でのみクラスマスクを広げるのは有効だが、本番プロファイルは C7 のみ TinyHeap (0x80) を維持するのが安全。
|
||||
|
||||
# Phase48: first-touch/page-fault 実験用プロファイルの固定
|
||||
- 評価は以下で統一し、pf/sys A/B の基準にする:
|
||||
- `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- perf stat メトリクス: ops/s, page-faults, task-clock(user/sys), cycles, instructions
|
||||
- 目的: HugePage/first-touch 削減などの実験をこのプロファイルで比較し、pf がどれだけ減るかを確認する。
|
||||
|
||||
# Phase45: 16–1024B perf stat A/B(HAKMEM vs mimalloc vs system, ws=400, iters=1,000,000, v2 OFF, C7 SAFE)
|
||||
|
||||
共通ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024`
|
||||
|
||||
| Allocator | Throughput (ops/s) | cycles | instructions | IPC | task-clock | user/sys | page-faults |
|
||||
|-----------|-------------------:|-------:|-------------:|----:|-----------:|---------:|------------:|
|
||||
| HAKMEM (C7_SAFE, v2 OFF) | 40,623,450 | 181,136,824 | 372,126,696 | 2.05 | 46.82 ms | 29.4 ms / 18.5 ms | 6,659 |
|
||||
| mimalloc | 112,895,946 | 38,800,615 | 59,184,115 | 1.53 | 10.66 ms | 10.31 ms / 1.41 ms | 146 |
|
||||
| system malloc | 92,111,481 | 52,144,974 | 107,607,240 | 2.06 | 12.54 ms | 12.27 ms / 1.36 ms | 133 |
|
||||
|
||||
所感/次手候補:
|
||||
- HAKMEM は sys 時間と page-fault が顕著(pf が mimallocの ~45x, sys 時間が高い)。pf/sys 寄りのボトルネックが支配的に見える。
|
||||
- 次の箱候補:
|
||||
- pf/sys 改善を狙う: Superslab/Warm Pool/pagefault 周りのCold Box見直し。
|
||||
- 命令数削減: front整理は済みなので、Tiny v1ホットパスや mid/large を軽くする路線も候補。
|
||||
|
||||
### メモ
|
||||
- HEAP_STATS(fast/slow)のダンプが出ない状態。今後のベンチでは `HAKMEM_TINY_HEAP_STATS[_DUMP]` の有効化経路を再確認する必要あり。
|
||||
|
||||
# Phase46: pf/sys 内訳の初期確認(HAKMEM, 16–1024B, ws=400, iters=1,000,000, v2 OFF, C7_SAFE)
|
||||
|
||||
- `perf record -o perf.data.pf -e page-faults -- ./bench_random_mixed_hakmem 1000000 400 1`
|
||||
- `perf report --stdio -i perf.data.pf`
|
||||
- サマリ: page-fault サンプルの ~96% が `__memset_avx2_unaligned_erms`(初回タッチ系)。カーネル側の munmap/madvise 由来はほぼ見えず、残っている 6.6k faults は first-write が中心と推定。
|
||||
- 基準プロファイル(以降 pf/sys A/B の基準にする想定):
|
||||
- `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- TODO / 次の箱候補:
|
||||
- WarmPool / Superslab 再利用が十分効いているかの stats 確認(該当 ENV を後続で調査)。
|
||||
- empty Superslab を即 OS 返却していないかのポリシー確認。
|
||||
- pf/sys 系の変更は上記プロファイルで揃えて A/B を取る。
|
||||
|
||||
# Phase46': WarmPool stats 1 回だけ確認(Mixed 16–1024B, ws=256, iters=20k, v2 OFF, C7_SAFE)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_WARM_POOL_STATS=1`
|
||||
- 結果(stderr 抜粋):
|
||||
- WarmPool-STATS: C7 hits=173 / misses=1 / prefilled=1(約 99.4% ヒット)。C2/C3/C4/C6 は warmup/prefill の 1 miss/1 prefill のみ。C0/C1/C5 は 0。
|
||||
- WARM logs: `REL_C7_WARM_PREFILL calls=1 slabs=1`, `REL_C7_CARVE attempts=173 success=173`, `REL_C7_WARM pop=174 push=173`.
|
||||
- Throughput: 43,809,979 ops/s(ws=256, iters=20k)。
|
||||
- 所感:
|
||||
- C7 は warm pool でほぼヒットしており、残り pf は first-write 優位という推定と矛盾しない。
|
||||
- 他クラスの warm pool はほぼ未使用(prefill 1 回のみ)。Mixed での pf/sys は C7 以外の Superslab 利用状況も別途見る必要あり。
|
||||
|
||||
# Phase49: Mixed 16–1024B userland-only CPU パス観測(v2 OFF, C7_SAFE)
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- perf stat(1M iters, ws=400, userlandのみ): throughput=41,000,086 ops/s, cycles=126,239,279, instructions=324,810,642(IPC≈2.57), branch-misses=1,186,675, time=0.0438s(user 0.0295s / sys 0.0143s)
|
||||
- perf record(cycles:u, 1M/400)上位シンボル(self%基準、子なし集計):
|
||||
- free 24.3%(libc wrapper経由の前段処理)
|
||||
- malloc 18.0%
|
||||
- main 15.3%(ベンチハーネス)
|
||||
- tiny_heap_page_pop 8.8%(TinyHeapBox hot pop)
|
||||
- hak_super_lookup 7.9%(frontからの Superslab 判定)
|
||||
- tiny_heap_page_becomes_empty 5.9%(empty 処理)
|
||||
- __memset_avx2_unaligned_erms 4.0%(ユーザランド側の初期化)
|
||||
- tiny_region_id_write_header 2.4%
|
||||
- 所感: ベンチ前段の malloc/free/main が重いが、TinyHeapBox 側では pop / super_lookup / empty が目立つ。Phase50 では TinyHeapBox(pop/empty + super_lookup 周辺)の枝削減を優先候補にする。
|
||||
|
||||
# Phase47: Superslab OS ポリシーと OS 呼び出し可視化
|
||||
- Superslab取得パス: LRU pop → 旧 cache pop → ss_os_acquire(mmap、必要なら MAP_POPULATE / prefault touch) の順。mmap 成功時に g_ss_mmap_count + SS_OS_STATS alloc を更新。
|
||||
- Superslab解放パス: registry unregister → LRU push(成功時は MADV_DONTNEED で lazy zero、今回 madvise カウント追加)→ 旧 cache push → どちらも満杯なら即 munmap(SS_OS_STATS free を加算)。ss_cache が容量縮小で munmap した場合も free をカウント。
|
||||
- 新 ENV: `HAKMEM_SS_OS_STATS=1` で alloc/free/madvise を destructor 1 行でダンプ(`[SS_OS_STATS] alloc=… free=… madvise=…`)。基準プロファイル(16–1024B, ws=400, iters=1M, C7_SAFE, v2 OFF)で 1 回回して OS 呼び出し回数を確認予定。
|
||||
- SS_OS_STATS(16–1024B, ws=400, iters=1M, C7_SAFE, v2 OFF): alloc=2 / free=3 / madvise=2 / mmap_total=2 → OS 呼び出しは少数。残る 6.6k pf は first-write 優位と見るのが妥当。
|
||||
|
||||
# Phase47: C6-heavy CPU ホットパスの初期観測(v2 OFF, C7_SAFE)
|
||||
|
||||
- ベンチ (ws=256, iters=20k, C6-heavy):
|
||||
- ENV: `HAKMEM_BENCH_MIN_SIZE=257 HAKMEM_BENCH_MAX_SIZE=768 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_TINY_FRONT_CLASS_STATS=1 HAKMEM_TINY_HEAP_STATS=1 HAKMEM_TINY_HEAP_STATS_DUMP=1`
|
||||
- Throughput: `39,457,304 ops/s`
|
||||
- FRONT_CLASS: cls6 alloc/free=5373、cls7 alloc=5692 free=4573
|
||||
- HEAP_STATS cls7: fast=5691 slow=1、C7_PAGE_STATS prepare_calls=1
|
||||
- perf stat (1M, ws=400, same ENV):
|
||||
- Throughput: `41,295,709 ops/s`
|
||||
- cycles=175,790,796 / instructions=368,496,560 (IPC≈2.10) / task-clock=42.36 ms (user 27.26 ms / sys 16.13 ms) / branch-misses=2,206,657
|
||||
- perf record (cycles, 1M, ws=400):
|
||||
- ホットスポットは匿名ページフォルト経路に集中(`__memset_avx2_unaligned_erms` → `handle_mm_fault` → `do_anonymous_page` が包含 60%超)。
|
||||
- ユーザランド側では `free`/`malloc` が目立つがカーネルの first-touch が支配的。
|
||||
- 所感: C6-heavy でも pf/sys が依然大きく、C6/Tiny フロントより先に first-touch/zero の扱いを考える必要がある(prefault/warm 再利用の検討)。
|
||||
|
||||
# Phase50: Tiny ヘッダモード (full/light/off) A/B(first-touch 実験の一部)
|
||||
- 目的: `tiny_region_id_write_header` のヘッダ書き込み/guard 初期化を軽量化することで page-fault / cycles がどこまで動くかを確認。
|
||||
- 実装概要:
|
||||
- ENV `HAKMEM_TINY_HEADER_MODE=full|light|off` を追加(未指定は full)。
|
||||
- `full`: 従来どおり region_id ヘッダと guard/初期化を常に書き戻す。
|
||||
- `light`: 既存ヘッダと一致する場合は再書き込みを避け、差分のみ最小限書く。
|
||||
- `off`: 既存ヘッダが壊れている場合のみ最小限のヘッダを書き戻し、guard 呼び出しや追加初期化はスキップ(free 整合性の最低限のみ保証)。旧 `HAKMEM_TINY_WRITE_HEADER=0` は off 相当として互換維持。
|
||||
- `FIRST_TOUCH_PAGEFAULT_REDUCTION_PLAN.md` に 3 モードの設計と ENV を明記(bench 専用 opt-in モードとして扱う)。
|
||||
|
||||
## Mixed 16–1024B (ws=400, iters=1M, PROFILE=C7_SAFE, v2 OFF, LARSON_FIX=1)
|
||||
- 共通 ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- HEADER_MODE=full:
|
||||
- Throughput: **42,399,649 ops/s**
|
||||
- cycles: 176,079,783
|
||||
- page-faults: 6,662
|
||||
- task-clock: 42.16 ms(user 25.1 ms / sys 17.8 ms)
|
||||
- HEADER_MODE=light:
|
||||
- Throughput: **38,752,779 ops/s**
|
||||
- cycles: 187,089,553
|
||||
- page-faults: 6,661
|
||||
- task-clock: 44.16 ms(user 31.5 ms / sys 13.2 ms)
|
||||
- HEADER_MODE=off:
|
||||
- Throughput: **39,330,655 ops/s**
|
||||
- cycles: 183,795,801
|
||||
- page-faults: 6,662
|
||||
- task-clock: 43.43 ms(user 29.3 ms / sys 15.2 ms)
|
||||
|
||||
### 所感(ヘッダモード実験)
|
||||
- page-fault 回数は full/light/off いずれも ≈6.66k とほぼ同一で、ヘッダ書き込み軽量化では first-touch page-fault は減らない。
|
||||
- cycles/ops はむしろ full が最も良く、light/off はそれぞれ約 -9% / -7% 程度の性能低下。判定・分岐コストがヘッダ書き込み削減効果を上回っている。
|
||||
- 結論として、現時点の実装では **運用デフォルトは full のままが最良**。light/off は bench 専用の実験モードとして残し、本番プロファイルでは使用しない前提とする。
|
||||
|
||||
# Phase52: Superslab HugePage 実験 (Mode A) – 初期結果
|
||||
- 目的: Superslab を HugePage (2MB) で確保する実験経路を追加し、page-fault / sys 時間がどこまで動くかを見る(研究専用)。
|
||||
- 実装概要:
|
||||
- ENV:
|
||||
- `HAKMEM_SS_HUGEPAGE_EXPERIMENT=1` で HugePage 経路を opt-in(デフォルト 0)。
|
||||
- `HAKMEM_SS_HUGEPAGE_SIZE` でページサイズを指定(現状は "2M" 前提で実装)。
|
||||
- `ss_os_acquire` 周辺に HugePage 試行を追加し、`MAP_HUGETLB | MAP_HUGE_2MB` で `mmap` を試し、失敗時は即通常の 1MB Superslab 経路にフォールバック。
|
||||
- SS_OS_STATS に `huge_alloc` / `huge_fail` を追加し、`HAKMEM_SS_OS_STATS=1` で `[SS_OS_STATS] alloc=.. free=.. madvise=.. huge_alloc=.. huge_fail=..` を 1 行出力。
|
||||
|
||||
## Mixed 16–1024B (ws=400, iters=1M, PROFILE=C7_SAFE, v2 OFF, LARSON_FIX=1)
|
||||
- 共通 ENV: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1 HAKMEM_SS_OS_STATS=1`
|
||||
- HugePage OFF:
|
||||
- Throughput: **41,464,379 ops/s**
|
||||
- cycles: 180,862,510
|
||||
- page-faults: 6,660
|
||||
- SS_OS_STATS: `alloc=2 free=4 madvise=2 mmap_total=2 fallback_mmap=0 huge_alloc=0 huge_fail=0`
|
||||
- HugePage ON (`HAKMEM_SS_HUGEPAGE_EXPERIMENT=1`, `HAKMEM_SS_HUGEPAGE_SIZE=2M`):
|
||||
- Throughput: **41,372,856 ops/s**
|
||||
- cycles: 177,305,948
|
||||
- page-faults: 6,662
|
||||
- SS_OS_STATS: `alloc=2 free=4 madvise=2 mmap_total=2 fallback_mmap=0 huge_alloc=0 huge_fail=0`
|
||||
|
||||
### 所感(HugePage 実験初期結果)
|
||||
- 現状の Superslab サイズ/条件では HugePage 経路が一度もヒットせず(`huge_alloc=0` / `huge_fail=0`)、通常 Superslab 経路のみが使用されている。
|
||||
- そのため HugePage ON/OFF で throughput / cycles / page-fault はほぼ同一となり、初期実装の段階では効果は「ゼロに近い」。
|
||||
- 2MB Superslab 専用クラスを設計するか、サイズ条件を緩めて HugePage を実際に使うかを決めないと、Mode A の効果は評価できない。
|
||||
- 一方で pf はすでに ≈6.6k と小さく、たとえ HugePage でさらに削っても全体への寄与は限定的なため、現時点では **CPU ホットパス側の最適化を優先し、HugePage 実験は research-only の位置付けに留める** のが妥当と見える。
|
||||
18
docs/analysis/TINY_C6_HOTPATH_ANALYSIS.md
Normal file
18
docs/analysis/TINY_C6_HOTPATH_ANALYSIS.md
Normal file
@ -0,0 +1,18 @@
|
||||
# C6-heavy Hotpath 分析 (Phase47, v2 OFF)
|
||||
|
||||
- プロファイル: `HAKMEM_BENCH_MIN_SIZE=257 HAKMEM_BENCH_MAX_SIZE=768 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- ベンチ:
|
||||
- `./bench_random_mixed_hakmem 20000 256 1` → `Throughput = 39,457,304 ops/s`
|
||||
- FRONT_CLASS: cls6 alloc/free=5373、cls7 alloc=5692 free=4573
|
||||
- perf stat (cycles,instructions,task-clock,branch-misses):
|
||||
- `./bench_random_mixed_hakmem 1000000 400 1`
|
||||
- cycles=175,790,796 / instructions=368,496,560 (IPC≈2.10)
|
||||
- task-clock=42.36 ms (user 27.26 ms / sys 16.13 ms), branch-misses=2,206,657
|
||||
- perf record (cycles, 1M, ws=400):
|
||||
- 上位は匿名ページフォルト経路が支配的(`__memset_avx2_unaligned_erms` → `handle_mm_fault` → `do_anonymous_page` → `alloc_anon_folio` 系で包含 60%+)。
|
||||
- ユーザランド側では `free`/`malloc` が目立つが、カーネル first-touch が主因。
|
||||
|
||||
## 次に削る箱(候補)
|
||||
- 最重: first-touch/ゼロイング由来の匿名ページフォルト
|
||||
- 候補策: class6 向けの温存ページ再利用 / prefault を増やし、ベンチの 1M/400 で pf/sys をさらに削る。
|
||||
- Tiny v1 自体の命令数は二次的(perf で目立たず)。C6 を TinyHeap に載せるよりも、先に pf 削減箱を検討するのが妥当。
|
||||
34
docs/analysis/TINY_CPU_HOTPATH_USERLAND_ANALYSIS.md
Normal file
34
docs/analysis/TINY_CPU_HOTPATH_USERLAND_ANALYSIS.md
Normal file
@ -0,0 +1,34 @@
|
||||
# TINY CPU Hotpath Userland Analysis (Phase49)
|
||||
|
||||
- プロファイル: Mixed 16–1024B, ws=400, iters=1,000,000
|
||||
`HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_HOTHEAP_V2=0 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- コマンド: `perf stat -e cycles:u,instructions:u,branch-misses:u ./bench_random_mixed_hakmem 1000000 400 1`
|
||||
`perf record -g -e cycles:u -o perf.data.mixed_u ./bench_random_mixed_hakmem 1000000 400 1`
|
||||
|
||||
## perf stat(userlandのみ)
|
||||
- Throughput: **41,000,086 ops/s**
|
||||
- cycles:u=126,239,279 / instructions:u=324,810,642 → IPC≈2.57
|
||||
- branch-misses:u=1,186,675
|
||||
- time=0.0438s(user 0.0295s / sys 0.0143s)
|
||||
|
||||
## perf record(cycles:u)上位シンボル(self%)
|
||||
- free: 24.3% — front入口/libc wrapper 部分
|
||||
- malloc: 18.0% — 同上
|
||||
- main: 15.3% — ベンチハーネス
|
||||
- tiny_heap_page_pop.lto_priv.0: 8.8% — TinyHeapBox ホット pop
|
||||
- hak_super_lookup.lto_priv.*: 7.9% — Superslab 判定(front→TinyHeapBox 境界前)
|
||||
- tiny_heap_page_becomes_empty.constprop.0: 5.9% — empty 遷移処理
|
||||
- __memset_avx2_unaligned_erms: 4.0% — ユーザランド初期化(first-touch)
|
||||
- tiny_region_id_write_header: 2.4% — header 書き込み
|
||||
- その他: __pthread_self / hak_free_at / tiny_heap_meta_flush_page などが1〜2%台
|
||||
|
||||
## 所感
|
||||
- ベンチ自身の malloc/free/main が大きいが、allocator 側では **tiny_heap_page_pop / hak_super_lookup / tiny_heap_page_becomes_empty** が目立つ。
|
||||
- userland側でも memset が残っており、first-touch 削減(ヘッダ書き込み削減や初期化遅延)余地がある。
|
||||
|
||||
## Phase50 で削るターゲット箱(提案)
|
||||
- **TinyHeapBox(C7/C6)の pop/empty + hak_super_lookup 前段**
|
||||
- super_lookup 依存の範囲チェックを軽量化 or キャッシュ化。
|
||||
- pop/empty 内の分岐を整理し、C7 SAFE の理想パス(current_page固定)に寄せる。
|
||||
- header write / memset を最小化する実験スイッチを検討。
|
||||
|
||||
@ -10,6 +10,32 @@ TinyHeapBox Design (C7 先行載せ替え)
|
||||
の 1 箇所に集約し、ホットパスは TinyHeap 内で完結させる。
|
||||
- A/B: `HAKMEM_TINY_HEAP_BOX=0` → 従来 Unified front、`=1` → TinyHeap front (いまは C7 のみ)。
|
||||
|
||||
TinyHeap Profile (ENV ショートカット)
|
||||
--------------------------------------
|
||||
- `HAKMEM_TINY_HEAP_PROFILE` を新設し、プロファイルで TinyHeap のデフォルト構成を切り替え可能にした(ENV が未指定のときのデフォルトを決める箱)。
|
||||
- LEGACY (デフォルト): TinyHeap OFF(class mask=0x00, meta_mode=0)。
|
||||
- C7_SAFE: TinyHeap ON, class mask=0x80 (C7 のみ), C7 meta_mode=1(SAFE)、`HAKMEM_TINY_HEAP_BOX` も自動 ON。C7_HOT は別途 1 にする。
|
||||
- C7_ULTRA_BENCH: class mask=0x80, meta_mode=2(ULTRA, bench専用)、`HAKMEM_TINY_HEAP_BOX` も ON。
|
||||
- CUSTOM: `HAKMEM_TINY_HEAP_CLASSES` / `HAKMEM_TINY_C7_META_MODE` を直接指定する従来挙動。
|
||||
- 優先順位:
|
||||
1. `HAKMEM_TINY_HEAP_BOX=0` なら TinyHeap 無効。
|
||||
2. `HAKMEM_TINY_HEAP_CLASSES` があればそのビットマスクを最優先。
|
||||
3. 無ければ `HAKMEM_TINY_HEAP_PROFILE` からデフォルト mask/meta_mode を決める。
|
||||
4. `HAKMEM_TINY_C7_META_MODE` があれば C7 meta_mode はそれを優先(無ければ profile→旧 `HAKMEM_TINY_C7_META_LIGHT` の順)。
|
||||
- 推奨フラグ例:
|
||||
- C7-only 比較: `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1 HAKMEM_TINY_LARSON_FIX=1`
|
||||
- Mixed 16–1024B: `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_C7_HOT=1`(C6 TinyHeap はデフォルト OFF のまま)
|
||||
|
||||
標準プロファイル (v1 締め)
|
||||
--------------------------
|
||||
- 推奨候補:
|
||||
- LEGACY … TinyHeap 全無効(基準)。
|
||||
- C7_SAFE … class mask=0x80, meta_mode=1(SAFE)に加え `HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0` をセットするのが標準。C6 は OFF。
|
||||
- bench/実験専用:
|
||||
- C7_ULTRA_BENCH(meta_mode=2)、C6 TinyHeap マスク (0x40/0xC0)、`HAKMEM_TINY_STATS_BATCH=1`。
|
||||
- デフォルト運用: PROFILE=LEGACY か PROFILE=C7_SAFE を手で選択し、C6 は明示しない限り OFF。詳細の次ステップ案は `docs/analysis/TINY_NEXT_STEPS.md` に記載。
|
||||
- Phase 20 追加: C6 Hot front を C7 と対称に導入(ENV `HAKMEM_TINY_C6_HOT=1` + class mask で有効化)。Front を薄くしても C6 TinyHeap は依然回帰が大きい。C6 は v1 では bench/実験用の位置づけに凍結。
|
||||
|
||||
主要構造 (core/box/tiny_heap_box.h)
|
||||
-----------------------------------
|
||||
- `tiny_heap_page_t`: ページ内 freelist/used/capacity と Superslab メタ (ss/meta/slab_idx/base) を保持。
|
||||
@ -37,6 +63,7 @@ Front Gate (core/front/malloc_tiny_fast.h)
|
||||
------------------------------------------
|
||||
- alloc: class_idx==7 & size==1024 かつ TinyHeapBox ON で `tiny_c7_alloc_fast()` に直行。それ以外は Unified Cache front。
|
||||
- free : Larson owner 判定に関係なく、TinyHeapBox ON + class7 なら meta 渡し free (`tiny_c7_free_fast_with_meta`) を優先。ss_fast_lookup 失敗時は `tiny_c7_free_fast()` で安全側。
|
||||
- Phase16: Route Snapshot Box (`tiny_route_env_box.h`) を追加し、起動時に `g_tiny_route_class[cls]` に TinyHeap/Legacy を確定。`malloc_tiny_fast` / `free_tiny_fast` は「size→class→route LUT→heap or legacy」の 1 分岐構造に整理。`HAKMEM_TINY_FRONT_CLASS_STATS(_DUMP)=1` で front クラス分布も取得可能。
|
||||
|
||||
C7 は TLS SLL を使わない(TinyHeap front ON 時)
|
||||
-----------------------------------------------
|
||||
@ -128,8 +155,78 @@ Phase 9: Tiny lane 判定の整理(TinyHeap を「成功」とみなす)
|
||||
- Mixed 16–1024B: OFF≈47.6M / C7のみ TinyHeap≈36.9M / C6+C7≈30.3M(警告なし)。
|
||||
- 今後: TinyHeap route の性能はまだ OFF より下がるケースがあるため、slow_prepare/hit 率の改善や C6 向け最適化を別フェーズで実施する。
|
||||
|
||||
Phase ULTRA: C7 meta モードの三段化(bench 専用 ULTRA 追加)
|
||||
------------------------------------------------------------
|
||||
- ENV `HAKMEM_TINY_C7_META_MODE` を追加(0:OFF, 1:SAFE meta-light=従来の delta+閾値 flush/clamp, 2:ULTRA)。従来の `HAKMEM_TINY_C7_META_LIGHT` は mode 未指定時の後方互換ゲートとして残し、mode を指定しない場合は SAFE=1 相当。
|
||||
- ULTRA (mode=2) は C7-only ベンチ専用。per-alloc で meta->used / ss_active_* を一切更新せず、delta/flush もスキップする。2024-xx-xx 時点で pop/push の meta->freelist/carved atomic も省略してオーバーヘッドを削減(Box 境界は維持するが Superslab/Tier の統計整合性は保証しない)。
|
||||
- SAFE (mode=1) はこれまでのページ境界 flush + 閾値 flush + attach clamp を維持し、本番で使うならこちら。
|
||||
- ベンチ (C7-only 20k/ws=64, Release, HEAP_BOX=1, HEAP_CLASSES=0x80, HOT=1, LARSON_FIX=1):
|
||||
- mode=0 (meta-light OFF): ≈38.7M ops/s(alloc_fast_current=10052 / alloc_slow_prepare=7681)
|
||||
- mode=1 (SAFE): ≈34.1M ops/s(alloc_fast_current=5837 / alloc_slow_prepare=5179)
|
||||
- mode=2 (ULTRA, bench): ≈41.6M ops/s(alloc_fast_current=5948 / alloc_slow_prepare=5068)
|
||||
- C7 current_page 固定化(ULTRA 専用):
|
||||
- ULTRA で tiny_heap_page_becomes_empty / mark_full の unlink を避け、free で常に current_page に据え置くように調整。
|
||||
- prepare は current_page が生きていれば即 return する軽量パスに変更し、C7-only 20k/ws=64 (mode=2) で ops≈52.0M / alloc_fast_current=11015 / alloc_slow_prepare=1 / prepare_calls=1 まで改善。
|
||||
- SAFE への逆輸入可否は別途検討(ULTRA は bench 限定、本番は OFF/SAFE を推奨)。
|
||||
- C7 current_page 可視化: `g_c7_page_stats`(prepare_calls / prepare_with_current_null / prepare_from_partial / current_set_from_free / current_dropped_to_partial)を `HAKMEM_TINY_C7_HEAP_STATS=1` で出力。現状 C7-only ULTRA では `prepare_with_current_null=prepare_calls` で free 側が current を保持できていないことが判明(要ポリシー見直し)。
|
||||
- 本番ドキュメントでは ULTRA を必ず OFF(mode=0/1)にすること。ULTRA で得た知見は安全側に逆輸入する前提。
|
||||
|
||||
Phase 12: SAFE (mode=1) への current_page 逆輸入
|
||||
-------------------------------------------------
|
||||
- SAFE でも C7 current_page を極力保持するように変更:
|
||||
- free: used>0 かつ free_list がある page は current に据え直し、empty でも delta を flush したうえで detach/publish せず current を保持(meta/active 整合性は維持)。
|
||||
- mark_full: C7 meta_light が current を指す場合は unlink せず据え置き。
|
||||
- prepare_page: C7 meta_light で current に空きがあれば即 return(refill へ降りない)。
|
||||
- ベンチ (C7-only, ws=64, HEAP_BOX=1, HEAP_CLASSES=0x80, HOT=1, LARSON_FIX=1):
|
||||
- SAFE mode=1 (meta-light) 20k: ≈46.6M ops/s、alloc_fast_current=11015 / alloc_slow_prepare=1 / free_fast_local=8726、C7_PAGE_STATS: prepare_calls=1。
|
||||
- SAFE 長時間: 100k≈46.7M、200k≈44.99M。`HAKMEM_TINY_C7_DELTA_DEBUG=1` でも `[C7_DELTA_SUMMARY] nonzero_pages=0 used_delta_sum=0 active_delta_sum=0` を確認。
|
||||
- ULTRA(mode=2) は bench 専用のまま。SAFE は meta/active の整合性を保ちつつ slow_prepare をほぼゼロに抑える構成になった。
|
||||
|
||||
今後の拡張ステップ
|
||||
------------------
|
||||
- C5〜C6 を TinyHeapBox に移す際は `tiny_heap_alloc_class_fast()` を流用し、Box 境界 (ページ補給/返却) の 1 箇所化を維持する。
|
||||
- `TINY_HEAP_MAX_PAGES_PER_CLASS` の調整と stats/Tier 更新の扱いは次フェーズで検証。
|
||||
- TLS SLL は今後 C0〜C6 のための箱として維持し、C7 は TinyHeapBox↔Superslab/Tier/Guard の二層構造に限定する。
|
||||
|
||||
Phase 13: クラス汎用 TinyHeap stats + C6/C7 混在ベンチ
|
||||
----------------------------------------------------
|
||||
- Stats をクラス配列 `TinyHeapClassStats g_tiny_heap_stats[TINY_NUM_CLASSES]` に拡張。ENV は `HAKMEM_TINY_HEAP_STATS` / `_DUMP`(従来の `_C7_` も互換)。fast/slow/fallback/prepare_fail/fail をクラスごとに記録できる。
|
||||
- Mixed 16–1024B (iters=20k, ws=256, LARSON_FIX=1):
|
||||
- TinyHeap OFF: ≈43.7M ops/s。
|
||||
- C7 SAFE のみ TinyHeap (`HEAP_BOX=1 HEAP_CLASSES=0x80 META_MODE=1 HOT=1`): ≈44.9M ops/s、`HEAP_STATS[7] fast=5691 slow_prepare=1`。
|
||||
- C6+C7 TinyHeap (`HEAP_CLASSES=0xC0` 同条件): ≈39.3M ops/s、`HEAP_STATS[6] fast=2744 slow=1`, `HEAP_STATS[7] fast=5691 slow=1`。
|
||||
- C6 偏重 (min=257 max=768, iters=20k, ws=256):
|
||||
- TinyHeap OFF: ≈43.8M ops/s。
|
||||
- C6 TinyHeap のみ (`HEAP_CLASSES=0x40`, C7 legacy): ≈38.5M ops/s、`HEAP_STATS[6] fast=5372 slow=1`。
|
||||
- C6+C7 TinyHeap (`HEAP_CLASSES=0xC0`, C7 SAFE): ≈40.6M ops/s、`HEAP_STATS[6] fast=5372 slow=1`, `HEAP_STATS[7] fast=5691 slow=1`。
|
||||
- 示唆:
|
||||
- C7 SAFE は mixed でも悪化せず、C7-only では legacy 超え → デフォルトで TinyHeap に載せる候補。
|
||||
- C6 は slow_prepare はほぼ 0 でも経路オーバーヘッドで throughput が落ちるため、当面は bench/実験用 (HEAP_CLASSES=0x40/0xC0) に留める。C6 を本格移行するなら current_page ポリシーや meta-light 相当の最適化が必要。
|
||||
- 推奨例: 本番寄せ C7 = `HEAP_BOX=1 HEAP_CLASSES=0x80 META_MODE=1`、C7-only bench = `META_MODE=2`(ULTRA, bench 専用)。C6 TinyHeap はデフォルト OFF のまま。
|
||||
|
||||
Phase 18: C6 SAFE 再計測とメタモード足場(挙動は安全寄せのまま)
|
||||
----------------------------------------------------------------
|
||||
- ENV `HAKMEM_TINY_C6_META_MODE` を追加(0/1)。現状は整合優先のため behavior mode=0 扱い(C6 は meta/active を per-alloc 更新、delta/flush は未使用)。C6 を TinyHeap に載せるときは `HAKMEM_TINY_HEAP_BOX=1 HAKMEM_TINY_HEAP_CLASSES=0x40/0xC0` を明示。
|
||||
- ベンチ (Release, iters=20k, ws=256, LARSON_FIX=1):
|
||||
- C6 偏重 (257–768B):
|
||||
- LEGACY (TinyHeap OFF): ≈44.28M ops/s。
|
||||
- C6 TinyHeap mask=0x40, META_MODE=0: ≈38.81M ops/s(cls6 fast=5372 / slow_prepare=1)。
|
||||
- C6 TinyHeap mask=0x40, META_MODE=1: ≈38.59M ops/s(同じく slow_prepare≒1)。
|
||||
- C6+C7 TinyHeap mask=0xC0, C6 META=1 / C7 META=1: ≈39.94M ops/s(cls6 fast=5372/slow=1, cls7 fast=5691/slow=1)。
|
||||
- Mixed 16–1024B:
|
||||
- LEGACY: ≈44.27M ops/s。
|
||||
- PROFILE=C7_SAFE (mask=0x80, C7 META=1): ≈43.64M ops/s。
|
||||
- C6 TinyHeap mask=0x40, META_MODE=0: ≈38.48M ops/s(cls6 fast=2744/slow=1)。
|
||||
- C6 TinyHeap mask=0x40, META_MODE=1: ≈38.66M ops/s(cls6 fast=2744/slow=1)。
|
||||
- C6+C7 TinyHeap mask=0xC0, C6 META=1 / C7 META=1: ≈39.49M ops/s(cls6 fast=2744/slow=1, cls7 fast=5691/slow=1)。
|
||||
- メモ: C6 は slow_prepare がほぼゼロでも回帰しているため、次は meta-light の安全な適用か Gate/Route 側の命令削減を検討。現状の C6 SAFE は「挙動は mode 0 相当(安全重視)」で、ベンチ比較用のスイッチとして位置付け。
|
||||
|
||||
Phase 17: C7 フロント超直線化(Gate→Heap を 1 本に)
|
||||
---------------------------------------------------
|
||||
- Route Snapshot ベースのヘルパ `tiny_c7_front_uses_heap()` を追加し、class7 が TinyHeap route かどうかを 1 LUT で判定。
|
||||
- `malloc_tiny_fast` 冒頭に C7 専用パスを追加: `size==1024 && tiny_c7_front_uses_heap()` のとき class/LUT/route を飛ばして `tiny_c7_alloc_fast` へ直行、miss 時だけ `tiny_cold_refill_and_alloc(7)` に静かにフォールバック。他クラスは従来の route LUT 経由を維持。
|
||||
- `free_tiny_fast` も class7 が Heap route のときに先に判定し、Larson owner 一致後は `tiny_c7_free_fast_with_meta` へ直行(route はスナップショットから 1 回だけ読む)。C7 以外は既存の Larson/SLL/UC 経路を継続。
|
||||
- ベンチ (Release, iters=20k, LARSON_FIX=1):
|
||||
- C7-only ws=64: PROFILE=LEGACY ≈37.1M / C7_SAFE ≈38.2M / C7_ULTRA_BENCH ≈45.3M ops/s。
|
||||
- Mixed 16–1024B ws=256: PROFILE=LEGACY ≈40.3M / C7_SAFE ≈40.7M ops/s(回帰を ~-1M まで圧縮)。
|
||||
- 次の選択肢メモ: (A) C6 TinyHeap を C7 SAFE 流(current 固定+meta-light SAFE)に寄せて再評価するか、(B) Tiny front/gate/UC の命令数削減を perf で詰めるかを検討。
|
||||
|
||||
@ -6,6 +6,13 @@ 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 と同等を維持するのが目的。
|
||||
|
||||
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。
|
||||
- C7-only (ws=64, iters=20k): v2 OFF **39.42M ops/s** / v2 ON **43.55M ops/s**(cls7 fast=11015 / slow=1、v2 alloc/free カウンタ増加)。
|
||||
- Mixed 16–1024B (ws=256, iters=20k): v2 OFF **40.44M ops/s** / v2 ON **36.58M ops/s**(cls7 fast=5691 / slow=1、v2 カウンタ増加)。
|
||||
- 現状の v2 は current/freelist を自前化しつつ、pop/free は v1 の `tiny_heap_page_pop/free_local` を呼ぶラッパ。C7-only はわずかにプラスだが、Mixed では lease 判定や v1 呼び出し重複のオーバーヘッドが目立つ。Phase34 で枝/ロード削減を検討。
|
||||
|
||||
ゴール
|
||||
-----
|
||||
- mimalloc の heap→page→block に近い形で C5/C6/C7 を 1 つの TinyHotHeap に統合し、Gate/UC/TLS-SLL をさらに薄くする。
|
||||
@ -93,3 +100,236 @@ Phase33 以降の選択肢
|
||||
--------------------
|
||||
- A) v2 で current_page+freelist の多ページ対応・ページ返却まで拡張し、Superslab への触れ方を v2 専用に寄せる(v1 はページ供給だけの Box にする)。
|
||||
- B) 当面 v2 は C7 限定のラッパ+単一ページ管理のまま据え置き、mid サイズや他クラスの箱に時間を回す。
|
||||
|
||||
Phase34: C7-only 専用モードに一旦限定& v2 用 stats 追加
|
||||
------------------------------------------------------
|
||||
- 方針: `HAKMEM_TINY_HOTHEAP_V2` は当面 **C7-only ベンチ/実験専用**。Mixed 16–1024B では v2 OFF 推奨(v1 C7_SAFE を使用)。
|
||||
- v2 専用 stats(ENV: `HAKMEM_TINY_HOTHEAP_V2_STATS=1`)を追加:
|
||||
- `alloc_calls / alloc_fast / alloc_lease / alloc_fb_v1`
|
||||
- `free_calls / free_fast / free_fb_v1`
|
||||
- destructor で `[HOTHEAP_V2_C7_STATS]` を 1 行 dump。
|
||||
- これで Mixed 時に「v2 がどこまでヒットしているか」「どれだけ v1 へフォールバックしているか」を切り分ける予定。
|
||||
- 次フェーズ候補:
|
||||
- パターンA: Mixed でも v2 のヒット率が高い → 枝/チェックの純コスト削減(hot path flatten)を検討。
|
||||
- パターンB: Mixed で v1 fallback が多い → v2 を C7-heavy 専用に割り切る or C7 判定をさらに絞る。
|
||||
|
||||
Phase35: v2 をいったん棚上げ(標準は v1+C7_SAFE に集中)
|
||||
---------------------------------------------------------
|
||||
- 観測結果: C7-only/Mixed いずれも v2 ON で大幅に劣化(alloc_fast がほぼ当たらず、lease→v1 fallback が支配)。
|
||||
- 運用方針:
|
||||
- `HAKMEM_TINY_HOTHEAP_V2=0` を標準(C7_SAFE v1 がデフォルト)。
|
||||
- v2 は C7-only の研究用に **明示的に ON** したときだけ使用。Mixed では OFF 推奨。
|
||||
- 設計メモ:
|
||||
- 現行 v2 は v1 へのフォールバック前提で、Hot path の枝コストと fallback 多発が主因で負けている。
|
||||
- 続けるなら current/freelist を完全に自前管理し、Superslab との境界だけ v2 専用に切る再設計が必要。
|
||||
|
||||
Phase36+: TinyHotHeap v2 を「Hot Box」として再定義する
|
||||
====================================================
|
||||
|
||||
背景(棚上げからの再出発)
|
||||
--------------------------
|
||||
- Phase35 までの v2 は「v1 TinyHeap/C7 SAFE の上に乗るラッパ」であり、
|
||||
- ページ供給・meta/ss_active/Remote/Stats はすべて v1 に委譲
|
||||
- current/freelist も最終的には v1 の API を介して触る構造
|
||||
だったため、**Mixed では構造的に v1 に勝てない** 状態だった。
|
||||
- Box Theory 的に見ると、
|
||||
- v2 の Hot 部と v1 TinyHeap の境界が曖昧(箱が二重になっている)
|
||||
- Cold Box(Superslab/Tier/Stats)との接点も v1/v2 の両方に分散
|
||||
しており、「境界 1 箇所」の原則から外れている。
|
||||
- そこで Phase36 以降は:
|
||||
> **TinyHeap v2 自体を per-thread Hot Box として再定義し、
|
||||
> Superslab / Tier / Remote / Stats / Learning をすべて外側の Cold Box に落とす**
|
||||
という方針に切り替える。
|
||||
|
||||
3 つの設計案(A/B/C)
|
||||
--------------------
|
||||
ここからの v2 には、Tiny 層をどこまで巻き取るかで 3 案ある。
|
||||
|
||||
1. A案: C5〜C7 を 1 つの TinyHotHeap に統合
|
||||
- `TinyHeapCtx`(per-thread)と `TinyClassHeap`(per-class)を定義し、
|
||||
current/partial/full/page freelist を 1 箱にまとめる標準案。
|
||||
- Superslab/Warm/Tier/Guard との境界は
|
||||
- alloc 側: `tiny_heap_refill_slow(th, ci)`
|
||||
- free 側: `tiny_heap_page_retire_slow(th, page)`
|
||||
だけに集約する。
|
||||
2. B案: C7 超ホットレーン + C5/C6 セミホットレーン
|
||||
- A案の上に「C7 専用 fast lane (`c7_fastlist + c7_current`)」を乗せて、
|
||||
mimalloc クラスの C7-only 性能を狙う二車線構造。
|
||||
3. C案: mimalloc 風 Segment+Page+Block をフル導入
|
||||
- Superslab/Tier/Guard を 1 つの Segment Box として再定義し、
|
||||
TinyHotHeap v2 の下に「Segment→Page→Block」の階層を敷き直す v3 相当案。
|
||||
|
||||
このドキュメントでは **A案(TinyHotHeap v2 = Hot Box)を第一候補** とし、
|
||||
実装を進めやすい形に具体化する。B/C 案は A が安定したあとに検討する。
|
||||
|
||||
TinyHotHeap v2 の箱構造(A案)
|
||||
------------------------------
|
||||
|
||||
Box Theory 観点での分割は次の通り:
|
||||
|
||||
- Hot Box: TinyHotHeapBox v2(per-thread)
|
||||
- 中身: `TinyHeapCtx` / `TinyClassHeap` / `TinyPageMeta`
|
||||
- 役割: heap→page→block のみを扱い、**Tiny 層の命令数を支配する唯一のホット層**。
|
||||
- Cold Box: Superslab/Segment + Tier + Guard + Remote
|
||||
- 役割: 大きなチャンク管理、Tier/HOT/DRAINING/FREE 状態管理、Remote Queue、Guard/Budget。
|
||||
- Hot からは `refill_slow` / `page_retire_slow` でしか触らない。
|
||||
- Policy Box: TinyPolicySnapshot
|
||||
- 役割: クラスごとの `heap_enabled` / `max_partial_pages` / `warm_cap` などを保持。
|
||||
- Hot は「現在のスナップショットを読むだけ」で、学習の有無を意識しない。
|
||||
- Stats Box / Learning Box:
|
||||
- 役割: page 単位の delta を受け取り、Cold 側で集計・可視化・学習を行う。
|
||||
- Hot は「page を refill/retire するとき」にだけ delta を渡す。
|
||||
|
||||
Hot Box のデータ構造(案)
|
||||
--------------------------
|
||||
|
||||
```c
|
||||
// ページ内メタデータ(ホット側が見る最小限)
|
||||
typedef struct TinyPageMeta {
|
||||
void* free_list; // ページ内の block 単位 LIFO freelist
|
||||
uint16_t used; // 使用中 block 数
|
||||
uint16_t capacity; // page あたりの総 block 数
|
||||
uint16_t class_idx; // Tiny class (C5〜C7)
|
||||
uint16_t flags; // HOT/PARTIAL/FULL など
|
||||
void* slab_ref; // Superslab/Segment 側への back pointer(Cold Box 用)
|
||||
} TinyPageMeta;
|
||||
|
||||
// クラスごとの Hot heap 状態
|
||||
typedef struct TinyClassHeap {
|
||||
TinyPageMeta* current; // 直近で使用中の page
|
||||
TinyPageMeta* partial_head; // 空きあり page のリスト
|
||||
TinyPageMeta* full_head; // full page(レアイベントのみ参照)
|
||||
} TinyClassHeap;
|
||||
|
||||
// TLS ごとの TinyHotHeap コンテキスト
|
||||
typedef struct TinyHeapCtx {
|
||||
TinyClassHeap cls[8]; // とりあえず C0〜C7。v2 では C5〜C7 を優先して有効化
|
||||
} TinyHeapCtx;
|
||||
```
|
||||
|
||||
Hot パス API(alloc/free)
|
||||
-------------------------
|
||||
|
||||
### alloc(Hot)
|
||||
|
||||
```c
|
||||
void* tiny_heap_alloc_fast(TinyHeapCtx* th, uint32_t ci) {
|
||||
TinyClassHeap* h = &th->cls[ci];
|
||||
TinyPageMeta* p = h->current;
|
||||
|
||||
// 1. current page から pop
|
||||
if (likely(p && p->free_list)) {
|
||||
void* block = p->free_list;
|
||||
p->free_list = *(void**)block;
|
||||
p->used++;
|
||||
return block;
|
||||
}
|
||||
|
||||
// 2. partial list から page を 1 枚取って current に昇格
|
||||
if (h->partial_head) {
|
||||
p = h->partial_head;
|
||||
h->partial_head = p->next; // intrusive list 想定
|
||||
h->current = p;
|
||||
// 取り直した current から改めて pop
|
||||
...
|
||||
}
|
||||
|
||||
// 3. ここで初めて Cold Box に降りる
|
||||
return tiny_heap_refill_slow(th, ci);
|
||||
}
|
||||
```
|
||||
|
||||
### free(Hot)
|
||||
|
||||
```c
|
||||
void tiny_heap_free_fast(TinyHeapCtx* th, void* ptr) {
|
||||
TinyPageMeta* p = tiny_page_of(ptr); // base から逆算 or side meta
|
||||
|
||||
// ページ内 freelist に push
|
||||
*(void**)ptr = p->free_list;
|
||||
p->free_list = ptr;
|
||||
p->used--;
|
||||
|
||||
if (unlikely(p->used == 0)) {
|
||||
// page 完全 free → Cold Box に返却
|
||||
tiny_heap_page_retire_slow(th, p);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Hot→Cold 境界(1 箇所ルール)
|
||||
------------------------------
|
||||
|
||||
- `tiny_heap_refill_slow(th, ci)`
|
||||
- Warm/Shared/Superslab/Segment/Tier/Guard に対して
|
||||
「class ci 用の page を 1〜数枚ください」と要求する唯一の関数。
|
||||
- 返ってきた page 群を `current` または `partial_head` に接続するだけで、
|
||||
meta->used / ss_active_* / Tier 状態は Cold Box 側が責任を持つ。
|
||||
- `tiny_heap_page_retire_slow(th, p)`
|
||||
- `p->used == 0` のときだけ呼ぶ。
|
||||
- page の返却/再利用(Warm Pool への push や Superslab への返却)と、
|
||||
Cold Stats/Guard の更新をまとめて処理する。
|
||||
|
||||
この 2 関数だけが Hot→Cold の境界となるため、
|
||||
Box Theory の「境界 1 箇所」に近い構造でデバッグ/A/B を行える。
|
||||
|
||||
Stats / Learning の配置
|
||||
----------------------
|
||||
|
||||
- Hot Box:
|
||||
- `TinyPageMeta` に軽量なローカルカウンタのみを持たせる(例: `uint16_t local_allocs;` など)。
|
||||
- `tiny_heap_refill_slow` / `tiny_heap_page_retire_slow` のタイミングで
|
||||
page 単位の delta を Cold Stats Box に flush する。
|
||||
- Cold Stats Box:
|
||||
- Superslab/Segment/class 単位の累積 stats を保持。
|
||||
- Learning Box からのみ読まれ、Hot Box は直接読まない。
|
||||
- Learning Box:
|
||||
- 一定周期で Stats から `TinyPolicySnapshot` を更新し、
|
||||
`heap_enabled[class]` / `max_partial_pages[class]` / `warm_cap[class]` を調整する。
|
||||
- Hot Box は `ci` 決定後に snapshot を読むだけで、
|
||||
Learning の ON/OFF によって命令数が変わらないようにする。
|
||||
|
||||
ENV / Gate / A/B 方針(v2 再開時のルール)
|
||||
-----------------------------------------
|
||||
|
||||
- ENV:
|
||||
- `HAKMEM_TINY_HOTHEAP_V2` … v2 Hot Box を有効化(デフォルト 0)。
|
||||
- `HAKMEM_TINY_HOTHEAP_CLASSES` … v2 適用クラスの bitmask。初期は C7-only (=0x80)、
|
||||
様子を見ながら 0xC0(C6+C7)→0xE0(C5〜C7) へ広げる。
|
||||
- Route Snapshot:
|
||||
- `g_tiny_route_class[ci]` に `TINY_ROUTE_HOTHEAP_V2 / TINY_ROUTE_HEAP_V1 / TINY_ROUTE_LEGACY` を設定。
|
||||
- Gate は `size→class→route` を 1 LUT + 1 分岐で決める薄い front を維持する。
|
||||
- A/B:
|
||||
- C7-only: `HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80` で v2 経路に切り替え、
|
||||
`=0` で v1 C7_SAFE に戻せるようにする。
|
||||
- Mixed 16–1024B: 当面は v1 C7_SAFE を基準とし、C7-only が安定してから C6/C5 を昇格させる。
|
||||
|
||||
将来の C 案(Segment+Page+Block)への橋渡し
|
||||
------------------------------------------
|
||||
|
||||
- 上記 A 案(TinyHotHeap v2 = Hot Box)は、
|
||||
mimalloc 風の Segment+Page+Block 構造(C 案)の **Hot 部分** とほぼ一致している。
|
||||
- 今後 C 案へ進める場合も、
|
||||
- Hot Box の API (`tiny_heap_alloc_fast/free_fast/refill_slow/page_retire_slow`) は変えず、
|
||||
- Cold Box 側で Superslab/Tier/Guard を「Segment Box」として整理する
|
||||
ことで、段階的に v3 へ移行できる。
|
||||
- このため、Phase36 以降の v2 実装は **「C 案の Hot 部だけを先に完成させる」** 方針で進める。
|
||||
|
||||
次にやること(実装タスクの箱化)
|
||||
--------------------------------
|
||||
|
||||
- docs/design/TINY_HOTHEAP_V2_IMPLEMENTATION_GUIDE.md に、
|
||||
実装手順(C7-only → C5〜C7 への拡張)と関数名/API の具体案をまとめる。
|
||||
- CURRENT_TASK.md に Phase36 として「TinyHotHeap v2 再定義(Hot Box 化)」を追加し、
|
||||
v2 の現状ステータスと今後のタスク窓口をこのドキュメントに集約する。
|
||||
|
||||
Phase36 (C7-only Hot Box 暫定実装)
|
||||
----------------------------------
|
||||
|
||||
- 状態: v2 は C7-only 実験箱のまま。デフォルトは `HAKMEM_TINY_HOTHEAP_V2=0`(v1 C7_SAFE が標準)。
|
||||
- 実装ポイント:
|
||||
- TLS 取得で全 class の storage_page を reset+stride 初期化。page node は storage を優先し、足りなければ calloc。
|
||||
- Hot パス: `tiny_hotheap_v2_alloc/free` が current_page → partial → refill を処理し、lease した v1 page を pop/push して meta/ss を同期。used==0 は retire_slow でリセット。
|
||||
- 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 経由の更新に寄せる必要がある。
|
||||
|
||||
46
docs/analysis/TINY_NEXT_STEPS.md
Normal file
46
docs/analysis/TINY_NEXT_STEPS.md
Normal file
@ -0,0 +1,46 @@
|
||||
Tiny Next Steps (Phase 19 メモ)
|
||||
===============================
|
||||
|
||||
事実スナップショット
|
||||
--------------------
|
||||
- 標準プロファイル (v1 締め)
|
||||
- LEGACY … TinyHeap 全無効。
|
||||
- C7_SAFE … class mask=0x80, meta_mode=1 に加え `HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0` をセット。C6 は OFF。
|
||||
- Bench/実験 … C7_ULTRA_BENCH、C6 TinyHeap マスク (0x40/0xC0)、`HAKMEM_TINY_STATS_BATCH=1` は bench 専用。
|
||||
- プロファイルと性能
|
||||
- C7_SAFE: C7-only 20k/ws64 ≈46.6M ops/s、Mixed 16–1024B は LEGACY と ±1M 以内(軽いマイナス〜誤差)。C7-heavy 向けの本番寄りプロファイル。
|
||||
- C7_ULTRA_BENCH: C7-only 20k/ws64 ≈52M ops/s(bench 専用、Superslab/Tier 整合は緩む)。
|
||||
- C6 TinyHeap: C6-heavy (min=257/max=768) LEGACY≈44.3M → TinyHeap≈38.6M。Mixed 16–1024B でも ≈38.5M〜39.5M と明確なマイナス。slow_prepare は ≒1 でも遅く、経路オーバーヘッドが支配的。
|
||||
- Cold Stats Box: STATS_BOX=1 は C7 SAFE で同等〜わずかプラス、BATCH=1 は C7-only/Mixed とも大幅マイナス(bench 専用扱い)。
|
||||
- クラス分布の目安(HEAP_STATS, ws=256/iters=20k)
|
||||
- Mixed 16–1024B + C7 SAFE: cls7 fast≈5691 / slow≈1。C6 を載せた場合でも cls6 fast≈2744 / slow≈1 と slow_prepare は低い。
|
||||
- C6-heavy: cls6 fast≈5372 / slow≈1。slow_prepare が少なくても throughput は低下。
|
||||
- 結論(現状)
|
||||
- C7 SAFE は C7-only で明確なプラス、Mixed でも許容レンジ → 推奨プロファイル候補。
|
||||
- C6 TinyHeap は現状ベンチ/実験専用。デフォルトでは OFF(mask=0x80 のまま)。
|
||||
|
||||
次の箱候補(2 本に絞る)
|
||||
-----------------------
|
||||
1) C6 TinyHeap を C7 SAFE 流に攻める箱
|
||||
- やること: current 固定・slow_prepare 抑制、meta-light/delta/閾値 flush の安全版を C6 に移植。Superslab/Tier の整合を Fail-Fast で確認しながら命令を削る。
|
||||
- リスク: 実装が複雑化するため delta debug/assert を増やす必要あり。効果が出なければ C6 TinyHeap は Bench 専用のまま。
|
||||
|
||||
2) Tiny front をさらに薄くする箱
|
||||
- 方向: Route Snapshot の上に C6/C7 用の直線 front(C7 HotPipeline 相当)を広げ、Gate/UC/TLS SLL 経路の命令数を削る。
|
||||
- 位置づけ: C6 TinyHeap 攻めとほぼ同じ課題の裏表。C6 current 固定+軽量 meta と合わせて検討。
|
||||
|
||||
3) Cold Tiny Stats Box を詰める箱
|
||||
- 役割: C7 SAFE で始めた page 内 delta/flush を「Cold Stats Box」に委譲し、meta->used / ss_active_* の更新をホットパスから切り離す。
|
||||
- 進捗: STATS_BOX を導入済み。BATCH=0 は性能同等、BATCH=1 は C7-only/Mixed とも大きく劣化(bench 専用)。`HAKMEM_TINY_STATS_BATCH` は当面 OFF 推奨。
|
||||
- 次の一手: BATCH=0 を前提に C5/C6 など他クラスへの適用可否を検討するか、別の箱(front/UC など)を優先するかを再評価。
|
||||
|
||||
当面の運用ルール
|
||||
----------------
|
||||
- デフォルト: PROFILE=LEGACY か PROFILE=C7_SAFE を手動選択。C7_SAFE 時は `HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0` をセット。C6 TinyHeap は明示しない限り OFF。
|
||||
- mimalloc 比較フラグ:
|
||||
- C7-only → `HAKMEM_BENCH_C7_ONLY=1 HAKMEM_TINY_HEAP_PROFILE=C7_SAFE HAKMEM_TINY_STATS_BOX=1 HAKMEM_TINY_STATS_BATCH=0 HAKMEM_TINY_LARSON_FIX=1`(ULTRA は研究用)。
|
||||
- Mixed 16–1024B → `HAKMEM_BENCH_MIN_SIZE=16 HAKMEM_BENCH_MAX_SIZE=1024 HAKMEM_TINY_LARSON_FIX=1` で PROFILE=LEGACY と PROFILE=C7_SAFE を並べて比較(C6 は載せない)。
|
||||
- C6 を触るときは必ず HEAP_CLASSES で class6 を明示し、`HAKMEM_TINY_HEAP_STATS[_DUMP]=1` で fast/slow を一緒に記録する。C6 は bench 専用のまま。
|
||||
- HotHeap v2 (C7 専用) の扱い:
|
||||
- 現状は C7-only でも v1 より遅く、Mixed では大きく回帰。標準は `HAKMEM_TINY_HOTHEAP_V2=0`(v1 C7_SAFE を使用)。
|
||||
- 研究/実験で使う場合のみ `HAKMEM_TINY_HOTHEAP_V2=1 HAKMEM_TINY_HOTHEAP_CLASSES=0x80` を明示し、`HAKMEM_TINY_HOTHEAP_V2_STATS=1` で fallback/fast 比率を観測する。結果が悪くてもよいベンチ専用モードとする。
|
||||
Reference in New Issue
Block a user