Files
hakmem/docs/analysis/TINY_CPU_HOTPATH_USERLAND_ANALYSIS.md
Moe Charm (CI) acc64f2438 Phase ML1: Pool v1 memset 89.73% overhead 軽量化 (+15.34% improvement)
## Summary
- ChatGPT により bench_profile.h の setenv segfault を修正(RTLD_NEXT 経由に切り替え)
- core/box/pool_zero_mode_box.h 新設:ENV キャッシュ経由で ZERO_MODE を統一管理
- core/hakmem_pool.c で zero mode に応じた memset 制御(FULL/header/off)
- A/B テスト結果:ZERO_MODE=header で +15.34% improvement(1M iterations, C6-heavy)

## Files Modified
- core/box/pool_api.inc.h: pool_zero_mode_box.h include
- core/bench_profile.h: glibc setenv → malloc+putenv(segfault 回避)
- core/hakmem_pool.c: zero mode 参照・制御ロジック
- core/box/pool_zero_mode_box.h (新設): enum/getter
- CURRENT_TASK.md: Phase ML1 結果記載

## Test Results
| Iterations | ZERO_MODE=full | ZERO_MODE=header | Improvement |
|-----------|----------------|-----------------|------------|
| 10K       | 3.06 M ops/s   | 3.17 M ops/s    | +3.65%     |
| 1M        | 23.71 M ops/s  | 27.34 M ops/s   | **+15.34%** |

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

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

8.3 KiB
Raw Blame History

TINY CPU Hotpath Userland Analysis (Phase49)

  • プロファイル: Mixed 161024B, 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 statuserlandのみ

  • 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.0438suser 0.0295s / sys 0.0143s

perf recordcycles: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 で削るターゲット箱(提案)

  • TinyHeapBoxC7/C6の pop/empty + hak_super_lookup 前段
    • super_lookup 依存の範囲チェックを軽量化 or キャッシュ化。
    • pop/empty 内の分岐を整理し、C7 SAFE の理想パスcurrent_page固定に寄せる。
    • header write / memset を最小化する実験スイッチを検討。

C7 v3 ON, Mixed 161024B (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 161024B (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.146.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 が 34% 程度残っている。
    • 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/sDEBUG/-O0 相当)

  • ss_map_lookup: 7.3% selffree 側での ptr→SuperSlab 判定が主、C7 v3 でも多い)
  • hak_super_lookup: 4.0% selflookup fallback 分)
  • classify_ptr: 0.64% selffree の入口 size→class 判定)
  • mid_desc_lookup: 0.43% selfmid 経路の記述子検索)
  • そのほか: free/malloc/main が約 30% 強、header write 系は今回のデバッグログに埋もれて確認できず。

所感:

  • 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 161024B (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 161024B, 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 161024B (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/BC7-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 は 23% まで微増(外れ時のフォールバック分)。
  • 所感: C7 v3 free の Superslab lookup 往復をほぼ除去でき、目標の +5〜10% に収まる結果。fast path 判定の TLS 走査が新たなホットスポットだが、現状コストは lookup より低く許容範囲。