Files
hakmem/docs/design/TINY_FRONT_V3_FLATTENING_GUIDE.md
2025-12-09 21:50:15 +09:00

93 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TINY FRONT v3 FLATTENING GUIDE
Mixed 161024B で C7 v3 を ON にしたときの前段ホットパスを薄くするための設計メモ。実装は別フェーズ担当 AI 向けの TODO リストです。
## 現状の malloc_tiny_fast 前段フロー(ざっくり)
- size → 「Tiny かどうか」判定。
- Tiny なら size → class_idx (C0〜C7) 変換。
- route LUT (`tiny_route_for_class(class_idx)`) で route 決定。
- route switch で Tiny v1 / v2 / v3 / legacy を呼び分け。
- C7 v3 は早期パスで direct に `so_alloc` / `so_free` へ行くが、他クラスの前段 if/switch がまだ残っている。
## perf で見えたボトルネックMixed 161024B, v3 ON, DEBUGビルド
- `tiny_region_id_write_header` ~6.7%
- `ss_map_lookup` ~3.6%
- `unified_cache_enabled` ~2.8%, `tiny_guard_is_enabled` ~2.2%
- `classify_ptr` (size→class 判定) ~1.4%
- `mid_desc_lookup` ~1.3%
- so_alloc/so_free 自体は合計 ~7%C7 v3 本体)。ここでは C7 以外の前段を削るのが目的。
## フラット化方針(次フェーズで実装する項目)
1) **size→class→route を 1 LUT + 1 switch に寄せる**
- C7 v3 の早期 if を最小限にし、C5/C6 などの分岐を共通 switch にまとめる。
- route の再判定・重複チェックを減らす。デバッグ/稀パスは `unlikely` 側へ。
2) **header/guard 系の前段整理**
- `tiny_region_id_write_header` の呼び出し回数・書き込みバイト数を確認し、必要最小限にする。
- guard 判定 (`tiny_guard_is_enabled` など) を Snapshot 側に寄せ、front では値を読むだけにする。
3) **Superslab 判定の軽量化**
- C7 v3 で self-thread が確定している場合の `ss_map_lookup` を避けられるか検討。
- lookup が必要なケースを TinyLookupBox に閉じ込め、ホットパスは lookup なしで通す。
## A/B 用プロファイル(固定)
- `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_POOL_V2_ENABLED=0`
- `HAKMEM_SMALL_HEAP_V3_ENABLED=1`
- `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80`
- ベンチ: `./bench_random_mixed_hakmem 1000000 400 1`
成功ライン: 上記環境で v3 ON のまま **+5〜10%** か、少なくとも回帰なし& HEAP_STATS に異常なし。
## Phase1 (done): フラグ判定のスナップショット化
- ENV ゲート:
- `HAKMEM_TINY_FRONT_V3_ENABLED` … デフォルト OFF有効時のみ v3 フロント経路)
- `HAKMEM_TINY_FRONT_V3_STATS` … 任意のデバッグカウンタ用
- Snapshot`TinyFrontV3Snapshot`)に
- unified_cache_on
- tiny_guard_on
- header_mode
を 1 回だけキャッシュし、front v3 ON のときは `unified_cache_enabled` / `tiny_guard_is_enabled` / `tiny_header_mode` の呼び出しをホットパスから排除。
- malloc/free とも snapshot を読むブロックに入り、UC/guard 判定をキャッシュ経由に統一。
- A/BMixed 161024B, ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFFで挙動変化なしslow=1 維持)。次は size→class 前段のフラット化に進める。
## Phase2-A: size→class LUT 化実装済み、A/B 待ち)
- ENV: `HAKMEM_TINY_FRONT_V3_LUT_ENABLED`(デフォルト OFF、v3 ON 時のみ有効化可能)。
- Tiny 前段専用の LUT (`TinyFrontV3SizeClassEntry`) を 1 回だけ構築し、front v3 が有効かつ LUT ON のときは
`malloc_tiny_fast` が size→class→route を 1 ルックアップで取得(挙動は既存 `hak_tiny_size_to_class` / route スナップショットに一致)。
- フォールバック: LUT が無効/範囲外/未初期化のときは従来の size→class ロジックに自動で戻る。
- Mixed 161024B A/Bws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF, front v3 ON
- LUT=0: 44.820M ops/s
- LUT=1: 45.231M ops/s+0.9%
- C7_PAGE_STATS: prepare_calls=2446短尺時と同値、HEAP_STATS は TinyHeap v1 経路外のため出力なし。
- 挙動回帰なしで微プラス。次は size→class→route 前段のさらなるフラット化を検討。
## Phase2-B: route fast pathLUT→1 switch
- ENV: `HAKMEM_TINY_FRONT_V3_ROUTE_FAST_ENABLED`(デフォルト OFF、front v3 + LUT ON 時だけ opt-in
- 仕様:
- size→class→route を LUT 2 バイト load で取得し、即 1 switch で v3/v2/v1/legacy に分岐。
- route helpertiny_route_for_class呼び出しをホットパスから外し、挙動は LUT 構築時のスナップショットに従う。
- ROUTE_FAST=0 のときは Phase2-A と同じ挙動に自動フォールバック。
- A/BMixed 161024B, ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF, front v3 ON, LUT ON
- route_fast=0: 45.066M ops/s
- route_fast=1: 44.821M ops/s約 -0.5%
- C7_PAGE_STATS: prepare_calls=2446、回帰なし。HEAP_STATS は TinyHeap v1 経路外のため未出力。
- メモ: 微小マイナスだったためデフォルトは ROUTE_FAST=0 のまま。size→class 前段や header/guard 整理の方が効果が出そう。
## Phase2-C: Header v3 (C7-only skip) 実験
- ENV:
- `HAKMEM_TINY_HEADER_V3_ENABLED`(デフォルト 0
- `HAKMEM_TINY_HEADER_V3_SKIP_C7`(デフォルト 0、C7 v3 alloc 時に tiny_region_id_write_header をスキップして簡易 1byte だけ書く)
- 実装ポイント:
- TinyFrontV3Snapshot に header_v3_{enabled,skip_c7} を追加。
- so_alloc_fast(C7) で header_v3_skip_c7 が有効なときは header を簡易 1store のみで書き、ガード/重い処理を省略。
- front/free 側の挙動は不変(ヘッダは class 判定用に 1byte だけ残す)。
- A/BMixed 161024B, ws=400, iters=1M, front v3/LUT ON, route_fast=0, C7 v3 ON
- header_v3=0: 44.29M ops/s, C7_PAGE_STATS prepare_calls=2446
- header_v3=1 + SKIP_C7=1: 43.68M ops/s約 -1.4%, prepare_calls=2446, v3 fallback/page_of_fail=0
- 所感: 短尺の header スキップだけでは改善なし。free 側の header 依存を外す or header_light 再設計を別フェーズで検討。