# 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 を最小化する実験スイッチを検討。 ## C7 v3 ON, Mixed 16–1024B (ws=400, iters=1,000,000, userland cycles) 環境: `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` - Throughput: **48.96M ops/s**(前回 v3 ON と同レンジ) - perf record `cycles:u` (171 samples, release build without symbols): - 上位は `free` / `malloc` / `main` の無名フレームに潰れてしまい、非C7 Tiny front の細かい関数名が出ず。 - シンボル再取得には DEBUG/記号付きビルドで perf し直す必要あり。 - 所感: C7 v3 以外のホットパス特定には、size→class→route 前段や unified cache hit パスを再シンボル化して見る必要がある。現状のバイナリでは細部が見えない。 ## Mixed 16–1024B (ws=400, iters=1,000,000, userland cycles, C7 v3 ON, DEBUGビルド) 環境: `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` ビルド: `make clean && CFLAGS='-O2 -g …' USE_LTO=0 OPT_LEVEL=2 NATIVE=0 make bench_random_mixed_hakmem` - Throughput: **46.1–46.3M ops/s**(リリース時の ~49M よりやや低いが符号付きビルドで許容) - perf record `cycles:u -F5000 --call-graph dwarf` (200 samples) の self% 上位(C7 v3 以外を抜粋): - free 23.5%, malloc 18.8%, main 13.7%(ベンチハーネス由来) - **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 1.4%(size→class 判定系) - mid_desc_lookup 1.3% - hak_free_at 0.9%, hak_pool_mid_lookup 0.7% - so_alloc/so_free 合計 ~7%(C7 v3 本体) - 所感(非C7 Tiny front 目線): - header 書き込み(tiny_region_id_write_header)が依然目立つ。 - Superslab 判定前の `ss_map_lookup` が 3–4% 程度残っている。 - route/guard 判定(unified_cache_enabled / tiny_guard_is_enabled / classify_ptr)が合わせて ~6% 程度。 - 次は「size→class→route 前段+header」をフラット化するターゲットが有力。 ## TF3 事前計測(DEBUGシンボル, front v3+LUT ON, C7-only v3) 環境: `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 HAKMEM_TINY_FRONT_V3_ENABLED=1 HAKMEM_TINY_FRONT_V3_LUT_ENABLED=1` ビルド: `BUILD_FLAVOR=debug OPT_LEVEL=0 USE_LTO=0 EXTRA_CFLAGS=-g` ベンチ: `perf record -F5000 --call-graph dwarf -e cycles:u -o perf.data.tiny_front_tf3 ./bench_random_mixed_hakmem 1000000 400 1` Throughput: **12.39M ops/s**(DEBUG/-O0 相当) - `ss_map_lookup`: **7.3% self**(free 側での ptr→SuperSlab 判定が主、C7 v3 でも多い) - `hak_super_lookup`: **4.0% self**(lookup fallback 分) - `classify_ptr`: **0.64% self**(free の入口 size→class 判定) - `mid_desc_lookup`: **0.43% self**(mid 経路の記述子検索) - そのほか: free/malloc/main が約 30% 強、header write 系は今回のデバッグログに埋もれて確認できず。 所感: ## Phase HF1(DEBUG, front v3+LUT+fast classify+mid_desc_cache ON) - ビルド: `CFLAGS='-O0 -g' USE_LTO=0 OPT_LEVEL=0 NATIVE=0` - ENV: `HAKMEM_PROFILE=MIXED_TINYV3_C7_SAFE`, `HAKMEM_MID_DESC_CACHE_ENABLED=1` - コマンド: `perf record -F 5000 --call-graph dwarf -e cycles:u -o perf.data.tiny_mixed_hf1 ./bench_random_mixed_hakmem 1000000 400 1` - self% 上位(perf_tiny_mixed_hf1.txt 抜粋): - tiny_alloc_gate_fast 16.85% - free 13.63% / malloc 13.34% / main 9.02%(ベンチ枠) - __memset_avx2_unaligned_erms 5.65%(初期化) - hak_super_registry_init 5.57%(初期化) - so_alloc_fast 2.41%, unified_cache_push 2.23% - tiny_front_v3_enabled 2.23%, tiny_front_v3_lut_lookup 2.21% - smallobject_hotbox_v3_can_own_c7 1.94% - tiny_region_id_write_header 1.82% - ss_map_lookup 1.61%, mid_desc_lookup_cached 0.98%, classify_ptr 0.65% 所感: TF3 + mid_desc_cache 適用後、ss_map_lookup/self% は 1.6% まで沈み、tiny_region_id_write_header が引き続き ~1.8% で上位。次の削り候補は header 書き込み回数削減 or front前段の小枝刈り。 - front v3 + LUT ON でも free 側の `ss_map_lookup` / `hak_super_lookup` が ~11% 程度残っており、ここを FAST classify で直叩きする余地が大きい。 - `classify_ptr` は 1% 未満だが、`ss_map_lookup` とセットで落とせれば +5〜10% の目標に寄せられる見込み。 ### Front v3 snapshot 導入メモ - `TinyFrontV3Snapshot` を追加し、`unified_cache_on / tiny_guard_on / header_mode` を 1 回だけキャッシュする経路を front v3 ON 時に通すようにした(デフォルト OFF)。 - Mixed 16–1024B (ws=400, iters=1M, C7 v3 ON, Tiny/Pool v2 OFF) で挙動変化なし(slow=1 維持)。ホットスポットは依然 front 前段 (`tiny_region_id_write_header`, `ss_map_lookup`, guard/route 判定) が中心。 ### Front v3 size→class LUT メモ(Phase2-A 実装済み、A/B これから) - ENV `HAKMEM_TINY_FRONT_V3_LUT_ENABLED` を追加(デフォルト OFF)。front v3 ON 時に size→class→route を Tiny 専用 LUT から 1 ルックアップで取得し、従来の `hak_tiny_size_to_class` + route 読みを代替する。 - LUT は起動時に既存の size→class 変換と route スナップショットをそのまま写経して構築するため挙動は変えない。 - A/B (Mixed 16–1024B, ws=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%) - HEAP_STATS は TinyHeap v1 経路外のため出力なし。C7_PAGE_STATS は prepare_calls=2446 で変化なし。 ### Header v3 (C7-only) 簡易スキップ実験 - ENV: `HAKMEM_TINY_HEADER_V3_ENABLED` / `HAKMEM_TINY_HEADER_V3_SKIP_C7` を追加。C7 v3 alloc 時だけ tiny_region_id_write_header を通さず 1byte store にする。 - Mixed 16–1024B (ws=400, iters=1M, front v3 ON, LUT ON, route_fast=0, Tiny/Pool v2 OFF): - 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、fallback/page_of_fail=0 - 所感: C7 v3 のヘッダ簡略だけでは perf 改善は見えず。free 側のヘッダ依存を落とす or header light/off を別箱で検討する必要あり。 ## TF3: ptr fast classify 実装後の A/B(C7-only v3, front v3+LUT ON) - Releaseビルド, ws=400, iters=1M, ENV は TF3 基準 (`C7_SAFE`, C7_HOT=1, v2/pool v2=0, v3 classes=0x80, front v3/LUT ON)。 - Throughput (ops/s): - PTR_FAST_CLASSIFY=0: **33.91M** - PTR_FAST_CLASSIFY=1: **36.67M**(約 +8.1%) - DEBUG perf(同ENV, gate=1, cycles@5k, dwarf): `ss_map_lookup` self が **7.3% → 0.9%**、`hak_super_lookup` はトップから消失。代わりに TLS 内のページ判定 (`smallobject_hotbox_v3_can_own_c7` / `so_page_of`) が合計 ~5.5% へ移動。`classify_ptr` は 2–3% まで微増(外れ時のフォールバック分)。 - 所感: C7 v3 free の Superslab lookup 往復をほぼ除去でき、目標の +5〜10% に収まる結果。fast path 判定の TLS 走査が新たなホットスポットだが、現状コストは lookup より低く許容範囲。