Files
hakmem/docs/analysis/MID_LARGE_CPU_HOTPATH_ANALYSIS.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

134 lines
11 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.

# MID/Large CPU Hotpath (Phase54)
- 条件: `./bench_mid_large_mt_hakmem 1 1000000 400 1` (Release)
`HAKMEM_TINY_HEAP_PROFILE=C7_SAFE`, `HAKMEM_TINY_C7_HOT=1`, `HAKMEM_TINY_HOTHEAP_V2=0`, `HAKMEM_TINY_LARSON_FIX=1`
- スループット: HAKMEM ≈28.1M ops/smimalloc 54.2M / system 15.3M は Phase53 より)
- perf stat (cycles:u): IPC≈2.4、page-faults≈7.4kPhase53 と同等)
## cycles:u ホットシンボルself%
- hak_pool_try_alloc.part.0 … 14.7% pool alloc ホットパス)
- worker_run … 9.2% (ドライバ側のループと malloc 呼び出しを含む)
- free / hak_free_at.constprop.0 … ~910%glibc free 連携+自前 free
- __memset_avx2_unaligned_erms … ~9%pool 初期化/clear と推定)
- mid_desc_lookup … 3.8%
- hak_super_lookup … 1.4%
- hak_pool_free.part.0 … 0.7%
## 所感
- pool 系hak_pool_try_alloc / hak_pool_freeと free/memset が支配的で、mid_desc_lookup と super_lookup も目立つ。
- kernel 枠の大きな inclusive% は free/memset 配下にぶら下がっており、userland 側の pool/front の命令数削減が効果的そう。
## Phase55 方針pool allocator ホットパス軽量化)
- スコープ: core/hakmem_pool.c / core/hakmem_smallmid.c / core/box/pool_* の pool fast path。
- hak_pool_try_alloc を直線化:
- 「TLS/local freelist hitなら即 return」を先頭に寄せ、debug/統計/slow は unlikely 側へ。
- mid_desc_lookup/クラス情報は入口で 1 回だけ計算し、TLS へのキャッシュを検討。
- hak_pool_free / hak_free_at:
- self-thread free は pool push を最優先にし、cross-thread/debug は unlikely に寄せる。
- free 時の memset/初期化が不要なケースを洗い出し、スキップ余地をメモ。
- mid_desc_lookup のキャッシュ:
- size→class→desc を入口で 1 回だけ決める仕組み(既存キャッシュの再利用も含め)を検討。
- 成功ラインbench_mid_large_mt_hakmem 1 1000000 400 1, Release):
- ops/s を 2829M → 3032M+5〜10%)へ。
- perf report で hak_pool_try_alloc + free 周辺 self% が数ポイント低下。
## Phase56 結果pool fast path 初期実装)
- 変更: PoolBlock→user 変換をヘルパに寄せ、TLS ring/lo pop と self-thread free push を直線化。owner 判定は mid_desc の 1 回 lookup で共有。
- ベンチC6-heavy, ws=256, iters=20k, C7_SAFE, v2 OFF: **25.9M ops/s**(目標 3032M に届かず、前回 2829M から回帰)。
- perf stat同条件 1M/400: cycles=225,766,496、instructions=528,335,613、task-clock=57.88ms、ops/s≈25.7M。
- 所感: fast-path整理だけでは効果薄く、むしろ低下。pool 内の memset/desc まわりやリング補充順序をより大胆に削らないと改善しない。次のステップとして追加の枝削減・キャッシュ導入を検討。
## Phase MD1mid_desc_lookup TLS キャッシュ)
- 目的: C6-heavy/mid で目立つ mid_desc_lookup を TLS 1 エントリでキャッシュし、サイズが同じリクエストが続くケースで self% を削る。
- ENV ゲート: `HAKMEM_MID_DESC_CACHE_ENABLED=1`(デフォルト OFF。miss 時は従来の `mid_desc_lookup` にフォールバック。
- baseline self%: mid_desc_lookup≈3.8%Phase54 perf, C7_SAFE
- A/BC6_HEAVY_LEGACY_POOLV1, 1M/400, flatten OFF, zero=full:
- cache OFF: 28.90M ops/s
- cache ON : 29.83M ops/s**+3.2%**segv/assert なし。
- Mixed 161024B (C7_SAFE front v3/LUT/fast classify ON): cache OFF 44.83M → ON 44.94M+0.3%。perf (cycles:u, release) では mid_desc_lookup は上位に出ず、self% 影響はごく小さい。
## Phase57 回帰トリアージpool v2 をゲート化)
- 変更: `HAKMEM_POOL_V2_ENABLED` を追加し、v1/v2 の pool 実装を env で切替。細分スイッチとして `HAKMEM_POOL_V2_BLOCK_TO_USER` / `HAKMEM_POOL_V2_TLS_FAST_PATH` を用意(デフォルト ON, v2 時のみ有効)。
- ベンチC6-heavy, 1M/400, Release:
- v1 (POOL_V2_ENABLED=0): **27.40M ops/s**
- v2 (POOL_V2_ENABLED=1): **24.73M ops/s**
- 所感: v2 の変更が回帰要因と判明。標準は v1 に戻し、スイッチ単位の A/B でどの改変が悪いかを切り分ける方針。
## Phase80: Pool v1 flatten 初回 A/BC6-heavy
- スコープ: pool v1 の自スレッドホットパスTLS ring/lo hitを別 Box として直線化し、mid/smallmidC6-heavyでの ops/s 向上を狙う。pool v2 は引き続き研究箱のまま触らない。
- 実装: `core/hakmem_pool.c``hak_pool_try_alloc_v1_flat` / `hak_pool_free_v1_flat` を追加し、TLS ring/lo hit 時は最小限の分岐だけで pop/push する経路を用意。miss 時や cross-thread/slow は従来の `_v1_impl` にフォールバックする構造にし、ENV `HAKMEM_POOL_V1_FLATTEN_ENABLED`デフォルト0`HAKMEM_POOL_V1_FLATTEN_STATS` で切替・統計を制御。
- ベンチ条件: `./bench_mid_large_mt_hakmem 1 1000000 400 1`Release`HAKMEM_BENCH_MIN_SIZE=257`, `MAX_SIZE=768`, `HAKMEM_TINY_HEAP_PROFILE=C7_SAFE`, `HAKMEM_TINY_C7_HOT=1`, `HAKMEM_TINY_HOTHEAP_V2=0`, `HAKMEM_SMALL_HEAP_V3_ENABLED=1`, `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80`, `HAKMEM_POOL_V2_ENABLED=0`, `HAKMEM_POOL_V1_FLATTEN_STATS=1`
- A/B 結果:
- flatten OFF (`POOL_V1_FLATTEN_ENABLED=0`): Throughput ≈ **23.12M ops/s**`[POOL_V1_FLAT] alloc_tls_hit=0 alloc_fb=0 free_tls_hit=0 free_fb=0`
- flatten ON (`POOL_V1_FLATTEN_ENABLED=1`): Throughput ≈ **25.50M ops/s**(約 +10%)、`alloc_tls_hit=499,870 alloc_fb=230 free_tls_hit=460,450 free_fb=39,649`
- 所感:
- Pool v1 の TLS fast path を分離・直線化するだけで、狙っていた +5〜10% の上限付近まで改善が出た。まだ free_fb がそこそこ残っており、page_of / 自スレ判定の精度を上げて free_fb を減らす余地がある。
- デフォルト運用は安全側を維持するため `HAKMEM_POOL_V1_FLATTEN_ENABLED=0` のままとし、C6-heavy/mid ベンチや実験時にのみ flatten 経路を ON にする Box として扱う。
## Phase81: Pool v1 flatten Phase2free_fb 理由分解)
- 変更: flatten stats に free fallback の内訳を追加page_null / not_mine / other。free で mid_desc が取れない場合は page_null、owner 不一致や TLS 無効による fallback は not_mine、それ以外は other としてカウント。
- ベンチ条件: `./bench_mid_large_mt_hakmem 1 1000000 400 1`Release`HAKMEM_TINY_HEAP_PROFILE=LEGACY`, `HAKMEM_TINY_HOTHEAP_V2=0`, `HAKMEM_POOL_V2_ENABLED=0`, `HAKMEM_POOL_V1_FLATTEN_ENABLED=1`, `HAKMEM_POOL_V1_FLATTEN_STATS=1`
- A/B:
- flatten OFF: **23.68M ops/s**、stats すべて 0。
- flatten ON : **25.90M ops/s**(約 +9.4%)、`alloc_tls_hit=499,870 alloc_fb=230 free_tls_hit=460,060 free_fb=40,039 page_null=40,039 not_mine=0 other=0`
- 所感: free fallback のほぼすべてが「mid_desc が取れず page=null」で発生している。owner mismatch はゼロ。今後は page_of/mid_desc 判定の精度を上げることで free_fb を減らす余地がある。
## Phase82: mid_desc マスク整合による free_fb 削減
- 変更: `mid_desc_register/lookup/adopt` が扱うページアドレスを `POOL_PAGE_SIZE` で正規化し、64KiB に未アラインな mmap でも mid_desc_lookup が一致するように修正。これにより false negative の page_null を減らす。
- ベンチ同条件、flatten ON, Release, tiny/pool v2 OFF, LEGACY tiny:
- flatten OFF: **23.68M ops/s**(参考値・前フェーズと同じ)。
- flatten ON : **26.70M ops/s**(約 +13% vs OFF`alloc_tls_hit=499,871 alloc_fb=229 free_tls_hit=489,147 free_fb=10,952 page_null=3,476 not_mine=7,476 other=0`
- 所感: page_null が大幅減≈40k→≈3.4k。not_mine が顕在化したため、次は owner 判定/自スレ判定の精度を軽く見直す余地がある。デフォルトは引き続き flatten OFF安全側で、bench/実験時のみ ON。
## Phase 82 Final: mid_desc initialization race fix と包括的 A/B ベンチ
### 根本原因の修正
- Phase 82 の full flatten が C7_SAFE モードでクラッシュしていた原因: `mid_desc_adopt()` が未初期化ミューテックスにアクセスする race condition
- C7_SAFE では TinyHeap ルーティングが C7-only であり、Pool が通常より早期に呼ばれる
- `mid_desc_init_once()``mid_desc_adopt()` より前に保証されていなかった
- 修正: `hak_pool_init_impl()` 冒頭で `mid_desc_init_once()` を強制実行 → 初期化順序を確定化
- この修正は本線(常に有効、すべてのプロファイルで)
### 包括的ベンチマーク結果 (C6_HEAVY_LEGACY_POOLV1, Release)
| フェーズ | 10K ops/s | 100K ops/s | 1M ops/s | 特記事項 |
|---------|-----------|-----------|---------|---------|
| **Phase 1 (ベースライン)** | 3.03M | 14.86M | 26.67M | 最適化なし、基準値 |
| **Phase 2 (Zero Mode Header)** | +5.0% | -2.7% | -0.2% | ML1: 小規模ワークロード向け |
| **Phase 3 (Full Flatten)** | +3.7% | **+6.1%** | -5.0% | 中規模100Kで最適化効果 |
| **Phase 4 (Combined)** | -5.1% | **+8.8%** | +2.0% | **最高パフォーマンス: 100K で +8.8%** |
| **Phase 5 (C7_SAFE Safety)** | NO CRASH | NO CRASH | NO CRASH | **クラッシュ完全回避** ✅ |
### 構成別デフォルト値(本線ポリシー)
**C7_SAFE プロファイル:**
- `HAKMEM_POOL_V1_FLATTEN_ENABLED=0` (デフォルト OFF
- `HAKMEM_POOL_ZERO_MODE=full` (デフォルト: フル zero、安全側
- `mid_desc_init_once()` 強制実行(クラッシュ防止、常に有効)
- ベンチ時の opt-in: `HAKMEM_POOL_V1_FLATTEN_ENABLED=1` / `HAKMEM_POOL_ZERO_MODE=header` で切り替え可能
**LEGACY / 研究用プロファイル:**
- `HAKMEM_POOL_V1_FLATTEN_ENABLED=0` (デフォルト OFF
- `HAKMEM_POOL_ZERO_MODE=full` (デフォルト: フル zero
- ベンチ時のみ `HAKMEM_POOL_V1_FLATTEN_ENABLED=1` で opt-in
### ワークロード特性別の最適化効果
| ワークロードサイズ | 最適な構成 | 改善率 | 備考 |
|-----------------|---------|--------|------|
| 小規模 (10K) | Phase 2 (Zero Mode) | +5.0% | オーバーヘッド増で複合モードは -5.1% |
| 中規模 (100K) | Phase 4 (Combined) | **+8.8%** | **最高効果を示す領域** |
| 大規模 (1M) | Phase 4 (Combined) | +2.0% | キャッシュ圧力で効果減少 |
### 所感
mid_desc 初期化順序の修正(`mid_desc_init_once()` の強制実行)は**本線として常に有効**。これにより:
- C7_SAFE モードでの未初期化ミューテックスクラッシュを完全排除
- Flatten と Zero Mode は箱として組み込まれ、ENV で opt-in/out が可能
- デフォルト構成では両機能とも OFF安全側維持
性能目標(+1325%)には未到達だが、**安全性の確保と中規模ワークロードでの +8.8% 改善** が主要な成果。1M 反復での -5%〜-0.2% 回帰は、より大規模データセットでのキャッシュ効率悪化に起因する可能性があり、今後の最適化テーマ。