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

8.7 KiB
Raw Blame History

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 … 任意のデバッグカウンタ用
  • SnapshotTinyFrontV3Snapshot)に
    • 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 等の局所的枝刈りで進める。