Files
hakmem/docs/analysis/RANDOM_MIXED_BOTTLENECK_ANALYSIS.md
Moe Charm (CI) a9ddb52ad4 ENV cleanup: Remove BG/HotMag vars & guard fprintf (Larson 52.3M ops/s)
Phase 1 完了:環境変数整理 + fprintf デバッグガード

ENV変数削除(BG/HotMag系):
- core/hakmem_tiny_init.inc: HotMag ENV 削除 (~131 lines)
- core/hakmem_tiny_bg_spill.c: BG spill ENV 削除
- core/tiny_refill.h: BG remote 固定値化
- core/hakmem_tiny_slow.inc: BG refs 削除

fprintf Debug Guards (#if !HAKMEM_BUILD_RELEASE):
- core/hakmem_shared_pool.c: Lock stats (~18 fprintf)
- core/page_arena.c: Init/Shutdown/Stats (~27 fprintf)
- core/hakmem.c: SIGSEGV init message

ドキュメント整理:
- 328 markdown files 削除(旧レポート・重複docs)

性能確認:
- Larson: 52.35M ops/s (前回52.8M、安定動作)
- ENV整理による機能影響なし
- Debug出力は一部残存(次phase で対応)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 14:45:26 +09:00

12 KiB
Raw Blame History

Random Mixed (128-1KB) ボトルネック分析レポート

Analyzed: 2025-11-16
Performance Gap: 19.4M ops/s → 23.4% of System (目標: 80%)
Analysis Depth: Architecture review + Code tracing + Performance pathfinding


Executive Summary

Random Mixed が 23% で停滞している根本原因は、複数の最適化層が C2-C764B-1KBの異なるクラスに部分的にしか適用されていない ことです。Fixed-size 256B (40.3M ops/s) との性能差から、class切り替え頻度と、各クラスの最適化カバレッジ不足 が支配的ボトルネックです。


1. Cycles 分布分析

1.1 レイヤー別コスト推定

Layer Target Classes Hit Rate Cycles Assessment
HeapV2 C0-C3 (8-64B) 88-99% Low (2-3) Working well
Ring Cache C2-C3 only 0% (OFF) N/A Not enabled
TLS SLL C0-C7 (全) 0.7-2.7% Medium (8-12) Fallback only
SuperSlab refill All classes ~2-5% miss High (50-200) Dominant cost
UltraHot C1-C2 11.7% Medium Disabled (Phase 19)

1.2 支配的ボトルネック: SuperSlab Refill

理由:

  1. Refill頻度: Random Mixed では class切り替え多発 → TLS SLL が複数クラスで頻繁に空になる
  2. Class-specific carving: SuperSlab内の各slabは「1クラス専用」→ C4/C5/C6/C7 では carving/batch overhead が相対的に大きい
  3. Metadata access: SuperSlab → TinySlabMeta → carving → SLL push の連鎖で 50-200 cycles

Code Path (core/tiny_alloc_fast.inc.h:386-450 + core/hakmem_tiny_refill_p0.inc.h):

tiny_alloc_fast_pop() miss
  ↓
tiny_alloc_fast_refill() called
  ↓
sll_refill_batch_from_ss() or sll_refill_small_from_ss()
  ↓
hak_super_registry lookup (linear search)
  ↓
SuperSlab -> TinySlabMeta[] iteration (32 slabs)
  ↓
carve_batch_from_slab() (write multiple fields)
  ↓
tls_sll_push() (chain push)

1.3 ボトルネック確定

最優先: SuperSlab refill コスト (50-200 cycles/refill)


2. FrontMetrics 状況確認

2.1 実装状況

実装完了 (core/box/front_metrics_box.{h,c})

Current Status (Phase 19-4):

  • HeapV2: C0-C3 で 88-99% ヒット率 → 本命層として機能中
  • UltraHot: デフォルト OFF (Phase 19-4 で +12.9% 改善のため削除)
  • FC/SFC: 実質 OFF
  • TLS SLL: Fallback のみ (0.7-2.7%)

2.2 Fixed vs Random Mixed の構造的違い

側面 Fixed 256B Random Mixed
使用クラス C5 のみ (100%) C3, C5, C6, C7 (混在)
Class切り替え 0 (固定) 頻繁 (各iteration)
HeapV2適用 C5 には非適用 C0-C3 のみ適用 (部分)
TLS SLL hit率 High (C5は SLL頼り) Low (複数class混在)
Refill頻度 低い (C5 warm) 高い (class ごとに空)

2.3 「死んでいる層」の候補

C4-C7 (128B-1KB) に対する最適化が極度に不足:

Class Size Ring HeapV2 UltraHot Coverage
C0 8B 1/3
C1 16B (OFF) 1/3
C2 32B (OFF) (OFF) 1/3
C3 64B (OFF) (OFF) 1/3
C4 128B 0/3 ← 完全未最適化
C5 256B 0/3 ← 完全未最適化
C6 512B 0/3 ← 完全未最適化
C7 1024B 0/3 ← 完全未最適化

衝撃的発見: Random Mixed で使用されるクラスの 50% (C5, C6, C7) が全く最適化されていない!


3. Class別パフォーマンスプロファイル

3.1 Random Mixed で使用されるクラス

コード分析 (bench_random_mixed.c:77):

size_t sz = 16u + (r & 0x3FFu);  // 16B-1040B の範囲

マッピング:

16-31B   → C2 (32B)   [16B requested]
32-63B   → C3 (64B)   [32-63B requested]
64-127B  → C4 (128B)  [64-127B requested]
128-255B → C5 (256B)  [128-255B requested]
256-511B → C6 (512B)  [256-511B requested]
512-1024B → C7 (1024B) [512-1023B requested]

実際の分布: ほぼ均一分布(ビット選択の性質上)

3.2 各クラスの最適化カバレッジ

C0-C3 (HeapV2): 実装済みだが Random Mixed では使用量少ない

  • HeapV2 magazine capacity: 16/class
  • Hit rate: 88-99%(実装は良い)
  • 制限: C4+ に対応していない

C4-C7 (完全未最適化):

  • Ring cache: 実装済みだが デフォルト OFF (HAKMEM_TINY_HOT_RING_ENABLE=0)
  • HeapV2: C0-C3 のみ
  • UltraHot: デフォルト OFF
  • 結果: 素の TLS SLL + SuperSlab refill に頼る

3.3 性能への影響

Random Mixed の大半は C4-C7 で処理されているのに、全く最適化されていない:

固定 256B での性能向上の理由:
- C5 単独 → HeapV2 未適用だが TLS SLL warm保持可能
- Class切り替えない → refill不要
- 結果: 40.3M ops/s

Random Mixed での性能低下の理由:
- C3/C5/C6/C7 混在
- 各クラス TLS SLL small → refill頻繁
- Refill cost: 50-200 cycles/回
- 結果: 19.4M ops/s (47% の性能低下)

4. 次の一手候補の優先度付け

候補分析

候補A: Ring Cache を C4/C5 に拡張 🔴 最優先

理由:

  • Phase 21-1 で既に 実装済みcore/front/tiny_ring_cache.{h,c}
  • C2/C3 では未使用(デフォルト OFF
  • C4-C7 への拡張は小さな変更で済む
  • 効果: ポインタチェイス削減 (+15-20%)

実装状況:

// tiny_ring_cache.h:67-80
static inline int ring_cache_enabled(void) {
    const char* e = getenv("HAKMEM_TINY_HOT_RING_ENABLE");
    // デフォルト: 0 (OFF)
}

有効化方法:

export HAKMEM_TINY_HOT_RING_ENABLE=1
export HAKMEM_TINY_HOT_RING_C4=128
export HAKMEM_TINY_HOT_RING_C5=128
export HAKMEM_TINY_HOT_RING_C6=64
export HAKMEM_TINY_HOT_RING_C7=64

推定効果:

  • 19.4M → 22-25M ops/s (+13-29%)
  • TLS SLL pointer chasing: 3 mem → 2 mem
  • Cache locality 向上

実装コスト: LOW (既存実装の有効化のみ)


候補B: HeapV2 を C4/C5 に拡張 🟡 中優先度

理由:

  • Phase 13-A で既に 実装済みcore/front/tiny_heap_v2.h
  • 現在 C0-C3 のみ(HAKMEM_TINY_HEAP_V2_CLASS_MASK=0xE
  • Magazine supply で TLS SLL hit rate 向上可能

制限:

  • Magazine size: 16/class → Random Mixed では小さい
  • Phase 17-1 実験: +0.3% のみ改善
  • 理由: Delegation overhead = TLS savings

推定効果: +2-5% (TLS refill削減)

実装コスト: LOWENV設定変更のみ

判断: Ring Cache の方が効果的候補A推奨


候補C: C7 (1KB) 専用 HotPath 実装 🟢 長期

理由:

  • C7 は Random Mixed の ~16% を占める
  • SuperSlab refill cost が大きい
  • 専用設計で carve/batch overhead 削減可能

推定効果: +5-10% (C7 単体で)

実装コスト: HIGH (新規設計)

判断: 後回しRing Cache + その他の最適化後に検討)


候補D: SuperSlab refill の高速化 🔥 超長期

理由:

  • 根本原因50-200 cycles/refillの直接攻撃
  • Phase 12 (Shared SuperSlab Pool) でアーキテクチャ変更
  • 877 SuperSlab → 100-200 に削減

推定効果: +300-400% (9.38M → 70-90M ops/s)

実装コスト: VERY HIGH (アーキテクチャ変更)

判断: Phase 21前提となる細かい最適化完了後に着手


優先順位付け結論

🔴 最優先: Ring Cache C4/C7 拡張 (実装済み、有効化のみ)
   期待: +13-29% (19.4M → 22-25M ops/s)
   工数: LOW
   リスク: LOW

🟡 次点: HeapV2 C4/C5 拡張 (実装済み、有効化のみ)
   期待: +2-5%
   工数: LOW
   リスク: LOW
   判断: 効果が小さいRing優先

🟢 長期: C7 専用 HotPath
   期待: +5-10%
   工数: HIGH
   判断: 後回し

🔥 超長期: SuperSlab Shared Pool (Phase 12)
   期待: +300-400%
   工数: VERY HIGH
   判断: 根本解決Phase 21終了後

5. 推奨施策

5.1 即実施: Ring Cache 有効化テスト

スクリプト (scripts/test_ring_cache.sh の例):

#!/bin/bash

echo "=== Ring Cache OFF (Baseline) ==="
./out/release/bench_random_mixed_hakmem 500000 256 42

echo "=== Ring Cache ON (C4/C7) ==="
export HAKMEM_TINY_HOT_RING_ENABLE=1
export HAKMEM_TINY_HOT_RING_C4=128
export HAKMEM_TINY_HOT_RING_C5=128
export HAKMEM_TINY_HOT_RING_C6=64
export HAKMEM_TINY_HOT_RING_C7=64
./out/release/bench_random_mixed_hakmem 500000 256 42

echo "=== Ring Cache ON (C2/C3 original) ==="
export HAKMEM_TINY_HOT_RING_ENABLE=1
export HAKMEM_TINY_HOT_RING_C2=128
export HAKMEM_TINY_HOT_RING_C3=128
unset HAKMEM_TINY_HOT_RING_C4 HAKMEM_TINY_HOT_RING_C5 HAKMEM_TINY_HOT_RING_C6 HAKMEM_TINY_HOT_RING_C7
./out/release/bench_random_mixed_hakmem 500000 256 42

期待結果:

  • Baseline: 19.4M ops/s (23.4%)
  • Ring C4/C7: 22-25M ops/s (24-28%) ← +13-29%
  • Ring C2/C3: 20-21M ops/s (23-24%) ← +3-8%

5.2 検証用 FrontMetrics 計測

有効化:

export HAKMEM_TINY_FRONT_METRICS=1
export HAKMEM_TINY_FRONT_DUMP=1
./out/release/bench_random_mixed_hakmem 500000 256 42 2>&1 | grep -A 100 "Frontend Metrics"

期待出力: クラス別ヒット率一覧Ring 有効化前後で比較)


5.3 長期ロードマップ

フェーズ 21-1: Ring Cache 有効化 (即実施)
  ├─ C2/C3 テスト(既実装)
  ├─ C4-C7 拡張テスト
  └─ 期待: 20-25M ops/s (+13-29%)

フェーズ 21-2: Hot Slab Direct Index (Class5+)
  └─ SuperSlab slab ループ削減
  └─ 期待: 22-30M ops/s (+13-55%)

フェーズ 21-3: Minimal Meta Access
  └─ 触るフィールド削減accessed pattern 限定)
  └─ 期待: 24-35M ops/s (+24-80%)

フェーズ 22: Phase 12 (Shared SuperSlab Pool) 着手
  └─ 877 SuperSlab → 100-200 削減
  └─ 期待: 70-90M ops/s (+260-364%)

6. 技術的根拠

6.1 Fixed 256B (C5) vs Random Mixed (C3/C5/C6/C7)

固定の高速性の理由:

  1. Class 固定 → TLS SLL warm保持
  2. HeapV2 非適用 → でも SLL hit率高い
  3. Refill少ない → class切り替えない

Random Mixed の低速性の理由:

  1. Class 頻繁切り替え → TLS SLL → 複数class で枯渇
  2. 各クラス refill多発 → 50-200 cycles × 多発
  3. 最適化カバレッジ 0% → C4-C7 が素のパス

差分: 40.3M - 19.4M = 20.9M ops/s

素の TLS SLL と Ring Cache の差:

TLS SLL (pointer chasing): 3 mem accesses
  - Load head: 1 mem
  - Load next: 1 mem (cache miss)
  - Update head: 1 mem

Ring Cache (array): 2 mem accesses
  - Load from array: 1 mem
  - Update index: 1 mem (同一cache line)

改善: 3→2 = -33% cycles

6.2 Refill Cost 見積もり

Random Mixed refill frequency:
  - Total iterations: 500K
  - Classes: 6 (C2-C7)
  - Per-class avg lifetime: 500K/6 ≈ 83K
  - TLS SLL typical warmth: 16-32 blocks
  - Refill per 50 ops: ~1 refill per 50-100 ops

  → 500K × 1/75 ≈ 6.7K refills

Refill cost:
  - SuperSlab lookup: 10-20 cycles
  - Slab iteration: 30-50 cycles (32 slabs)
  - Carving: 10-15 cycles
  - Push chain: 5-10 cycles
  Total: ~60-95 cycles/refill (average)

Impact:
  - 6.7K × 80 cycles = 536K cycles
  - vs 500K × 50 cycles = 25M cycles total
  = 2.1% のみ

理由: refill は相対的に少ない、むしろ TLS hit rate の悪さと
class切り替え overhead が支配的

7. 最終推奨

項目 内容
最優先施策 Ring Cache C4/C7 有効化テスト
期待改善 +13-29% (19.4M → 22-25M ops/s)
実装期間 < 1日 (ENV設定のみ)
リスク 極低(既実装、有効化のみ)
成功条件 23-25M ops/s 到達 (25-28% of system)
次ステップ Phase 21-2 (Hot Slab Cache)
長期目標 Phase 12 (Shared SS Pool) で 70-90M ops/s

End of Analysis