## Phase PERF-ULTRA-REBASE-1 実施 - C4-C7 ULTRA 全て ON 状態での CPU ホットパス計測 - Mixed 16-1024B, 10M cycles での perf 分析 - **発見**: C7 ULTRA alloc が新しい最大ボトルネック(7.66% self%) ## ホットパス分析結果 | 順位 | 関数 | self% | |------|------|-------| | #1 | C7 ULTRA alloc | **7.66%** ← 最大ボトルネック | | #2 | C4-C7 ULTRA free群 | 5.41% | | #3 | gate/front前段 | 2.51% ← 既に十分薄い | | #4 | header | < 0.17% ← ULTRA で削減済み | ## 戦略転換(重要) これまで: 新しい箱や世代(v4/v5/v6)を追加 → 今後: 既に当たりが出ている ULTRA 内部を細かく削る 理由: - v6/v5 拡張は -12〜33% の大幅回帰 - gate/front や header はもう改善の余地が少ない - C7 ULTRA alloc の 7.66% → 5-6% 削減で全体効果 2-3% ## Phase PERF-ULTRA-ALLOC-OPT-1 計画策定 - ターゲット: tiny_c7_ultra_alloc() の hot path を直線化 - 施策: 1. TLS ヒットパスの直線化(env check/snapshot 削除) 2. TLS freelist レイアウト最適化(L1 キャッシュ親和性) 3. segment/page_meta アクセスの確認(slow path 確認) - 計測: C7-only + Mixed での A/B テスト - 期待: 7.66% → 5-6%、全体で +2-3M ops/s ## ドキュメント更新 - CURRENT_TASK.md: PERF-ULTRA-REBASE-1 結果と ALLOC-OPT-1 計画を追記 - TINY_C7_ULTRA_DESIGN.md: Phase PERF-ULTRA-ALLOC-OPT-1 セクション追加 - NEW: docs/analysis/PERF_ULTRA_ALLOC_OPT_1_PLAN.md - 詳細な実装計画書 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
14 KiB
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_lookupself が 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 より低く許容範囲。
Phase PERF-ULTRA-REBASE-1 Results (2025-12-11 19:43:49)
計測環境
- 日時: 2025-12-11 19:43:49
- ワークロード: Mixed 16-1024B, ws=8192, iters=10,000,000
- ENV設定:
HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1HAKMEM_TINY_C6_ULTRA_FREE_ENABLED=1HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=1HAKMEM_TINY_C4_ULTRA_FREE_ENABLED=1- その他 ULTRA 以外のフラグは OFF(v6/v4/v5/free-front-v3 等)
- perf コマンド:
perf record -F 5000 --call-graph dwarf -e cycles:u - Throughput: 31.61M ops/s
- Samples: 1842 samples, 約1.36B cycles
perf report 主要関数 self% トップ20
- free: 25.48%(libc wrapper/ベンチ由来)
- main: 23.60%(ベンチマークハーネス)
- malloc: 21.13%(libc wrapper/ベンチ由来)
- tiny_c7_ultra_alloc: 7.66%
- tiny_c7_ultra_free: 3.50%
- so_free: 2.47%
- so_alloc_fast: 2.39%
- tiny_c7_ultra_page_of: 1.78%
- classify_ptr: 1.15%
- tiny_c7_ultra_segment_from_ptr: 0.96%
- tiny_front_v3_lut_lookup: 0.91%
- ss_map_lookup: 0.79%
- tiny_c5_ultra_free_fast: 0.69%
- hak_free_at: 0.68%
- tiny_c6_ultra_free_fast: 0.54%
- tiny_guard_is_enabled: 0.45%
- tiny_c6_ultra_free_tls: 0.34%
- tiny_heap_page_becomes_empty: 0.23%
- tiny_c4_ultra_free_fast: 0.17%
- tiny_c5_ultra_free_tls: 0.17%
カテゴリ別集計
- ベンチマーク関連(main + free + malloc wrapper): 70.21%
- C4-C7 ULTRA free関数群の合計: 5.41%
- tiny_c7_ultra_free: 3.50%
- tiny_c5_ultra_free_fast: 0.69%
- tiny_c6_ultra_free_fast: 0.54%
- tiny_c6_ultra_free_tls: 0.34%
- tiny_c4_ultra_free_fast: 0.17%
- tiny_c5_ultra_free_tls: 0.17%
- C7 ULTRA alloc: 7.66%
- so_alloc系(v3 backend alloc): 3.60%
- so_alloc_fast: 2.39%
- so_alloc: 1.21%
- so_free系(v3 backend free): 2.47%
- gate/front関連: 2.51%
- classify_ptr: 1.15%
- tiny_front_v3_lut_lookup: 0.91%
- tiny_guard_is_enabled: 0.45%
- page_of/segment判定: 2.74%
- tiny_c7_ultra_page_of: 1.78%
- tiny_c7_ultra_segment_from_ptr: 0.96%
- ss_map_lookup(Superslab判定): 0.79%
- hak_free_at: 0.68%
- tiny_heap_page_becomes_empty: 0.23%
分析コメント
-
C7 ULTRA alloc が最大ホットスポット(7.66%)
- C7 ULTRA の allocate パスが allocator 内で最も重いボトルネック
- 次点は ULTRA free 群(5.41%)だが、alloc が約1.4倍重い
-
so_alloc系(v3 backend)が3.60%で続く
- C7 v3 の backend alloc 処理が依然として可視
- so_free は2.47%でバランス良好
-
page_of/segment判定が2.74%
- tiny_c7_ultra_page_of(1.78%)とsegment_from_ptr(0.96%)の合計
- ULTRA free内でのptr→page/segment解決コストが目立つ
-
gate/front前段は2.51%に留まる
- classify_ptr(1.15%)、LUT lookup(0.91%)、guard判定(0.45%)
- 以前のフェーズより改善されており、現時点では相対的に軽い
-
ss_map_lookup は0.79%まで低下
- TF3 + PTR_FAST_CLASSIFY の効果で Superslab lookup が大幅減
- 依然残っているが、優先度は下がった
-
header書き込みが不可視
- tiny_region_id_write_header が上位20に入っていない(< 0.17%)
- ULTRA経路では header 書き込みコストが削減されている可能性
次の候補箱(ボトルネック優先順位)
-
最優先: C7 ULTRA alloc(7.66%)
- tiny_c7_ultra_alloc の内部最適化が最大の削減ポテンシャル
- キャッシュヒット率向上、TLS構造簡素化、分岐削減などを検討
-
第2優先: C4-C7 ULTRA free群(5.41%)
- 特に tiny_c7_ultra_free(3.50%)が中心
- page_of/segment判定(2.74%)との重複があるため、ptr解決の高速化が有効
-
第3優先: so_alloc系 backend(3.60%)
- C7 v3 の backend alloc 処理の軽量化
- fast path のインライン化や TLS キャッシュ強化
-
第4優先: page_of/segment判定(2.74%)
- ptr→page/segment 解決の最適化
- TLS キャッシュや LUT ベースの高速化を検討
-
監視対象: gate/front前段(2.51%)
- 現状は許容範囲だが、さらなる改善余地あり
- classify_ptr の fast path 強化や LUT の効率化
所感
- C7 ULTRA alloc が明確な最大ボトルネックとして浮上。次のフェーズでは alloc パスの内部最適化(TLS キャッシュヒット率向上、構造簡素化、分岐削減)に注力すべき。
- ULTRA free 群も5.41%と無視できないが、alloc が約1.4倍重いため、alloc を先に削るのが効率的。
- gate/front 前段は以前のフェーズより改善されており、現時点での優先度は下がった。
- header 書き込みが上位20に入っていないのは、ULTRA 経路での削減効果が出ている可能性がある。