Files
hakmem/docs/design/TINY_FRONT_V3_FLATTENING_GUIDE.md
Moe Charm (CI) 406a2f4d26 Incremental improvements: mid_desc cache, pool hotpath optimization, and doc updates
**Changes:**
- core/box/pool_api.inc.h: Code organization and micro-optimizations
- CURRENT_TASK.md: Updated Phase MD1 (mid_desc TLS cache: +3.2% for C6-heavy)
- docs/analysis files: Various analysis and documentation updates
- AGENTS.md: Agent role clarifications
- TINY_FRONT_V3_FLATTENING_GUIDE.md: Flattening strategy documentation

**Verification:**
- random_mixed_hakmem: 44.8M ops/s (1M iterations, 400 working set)
- No segfaults or assertions across all benchmark variants
- Stable performance across multiple runs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-10 14:00:57 +09:00

121 lines
8.7 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 再設計を別フェーズで検討。
## Phase TF3: ptr fast classify設計メモ / 実装TODO
- ENV ゲート(デフォルト 0、A/B でのみ ON
- `HAKMEM_TINY_PTR_FAST_CLASSIFY_ENABLED`
- 目的: C7 v3 free の入口で「明らかに Tiny/C7 のページ」だけを fast path に送り、`classify_ptr → ss_map_lookup → mid_desc_lookup` の往復を避ける。外れたら必ず従来の classify_ptr 経路へフォールバックする。
- デザインfree 側, malloc_tiny_fast.h 想定):
1. gate C7 v3 が有効かを Snapshot で確認C6/Pool/off のときは何もしない)。
2. ptr から TLS context / so_page_of / page metadata だけで「self-thread の C7 v3 ページ」かを判定。
3. 判定 OK → `ss_map_lookup` を通さず C7 v3 の free 直行。
4. 判定 NG → 現行の classify_ptr/ss_map_lookup にそのまま落とすBox 境界は不変)。
- 実装担当向け TODO:
- ENV gate 追加(デフォルト 0
- free 入口に C7 v3 専用 fast classify を追加(必ずフォールバックあり)。
- A/B: Mixed 161024B, C7 v3 ON, front v3/LUT ON, Tiny/Pool v2 OFF
- baseline: PTR_FAST_CLASSIFY=0
- trial: PTR_FAST_CLASSIFY=1
- 期待: segv/assert なし、`ss_map_lookup / classify_ptr` self% 減、ops/s が +数%〜+10% 方向。
### 実装後メモ2025/TF3
- 実装: `tiny_ptr_fast_classify_enabled` ゲート追加、free 入口で C7 v3 の TLS ページ判定(`smallobject_hotbox_v3_can_own_c7`)が当たれば `so_free` へ直行。外れは従来 route/classify へフォールバック。
- Mixed 161024B (C7-only v3, front v3+LUT ON, v2/pool v2 OFF, ws=400, iters=1M, Release):
- OFF: 33.9M ops/s → ON: 36.7M ops/s約 +8.1%)。
- DEBUG perf (cycles@5k, dwarf, gate=1): `ss_map_lookup` self が 7.3% → 0.9%、`hak_super_lookup` はトップ外へ。TLS 走査 (`smallobject_hotbox_v3_can_own_c7`) が ~5.5% に現れるが lookup 往復より低コスト。
- ロールアウト案: Mixed 基準でプラスが安定しているため、front v3/LUT ON 前提では fast classify もデフォルトON候補。ENV=0 で即オフに戻せる構造は維持。
## メモ: gate 大規模再構成TG2は回帰で撤退
- tiny_alloc_gate_box を「size→class→route 判定を前段に集約」する形に再構成し、malloc_tiny_fast_dispatch を導入したが、Mixed 161024B (MIXED_TINYV3_C7_SAFE, Release) で **約 -14%** の回帰を確認。
- 変更は破棄し、gate は従来の薄いラッパに戻した。今後は gate 全体をいじらず、ヘッダ書き込み削減・ptr classify・header/route snapshot 等の局所的枝刈りで進める。