Files
hakmem/docs/analysis/PERF_ULTRA_REFILL_OPT_1_PLAN.md
Moe Charm (CI) 17b6be518b Document Phase PERF-ULTRA-REFILL-OPT-1 plan: C7 ULTRA refill optimization
Created comprehensive plan for next optimization phase:
- Target: tiny_c7_ultra_page_of (1.78% self%)
- Options: Page size macro, segment learning in alloc, TLS page cache
- Expected gain: 0.5-1% overall throughput improvement

All measurement and analysis phases completed for current iteration.
Next: Implement Phase PERF-ULTRA-REFILL-OPT-1
2025-12-11 21:37:57 +09:00

6.0 KiB
Raw Blame History

Phase PERF-ULTRA-REFILL-OPT-1 計画C7 ULTRA refill パス最適化

背景

現状分析 (PERF-ULTRA-REBASE-4)

Mixed 16-1024B ワークロードiters=10M, ws=8192のホットパス分析結果

関数 self% 最適化状況
free (dispatcher) 25.48% snapshot 済みENV/route 初期化時のみ)
malloc (dispatcher) 21.13% LUT 化済みsize_to_class/route 両方 0 calls
tiny_c7_ultra_alloc 7.66% ⚠️ 既に最適化済み(直線化限界)
tiny_c7_ultra_free 3.50% TLS push + segment learning
so_free 2.47% v3 backend最適化機会未調査
so_alloc_fast 2.39% v3 backend最適化機会未調査
tiny_c7_ultra_page_of 1.78% 🎯 refill path最適化ターゲット
so_alloc 1.21% -
classify_ptr 1.15% -

重要な発見

  1. Dispatcher/Gate レベルの最適化は既に完了

    • free dispatcher (25%) = malloc/free の C API コール + routing overhead
    • malloc dispatcher (21%) = 内部的には LUT/ULTRA で最適化済み
    • これ以上削減するには architecture レベルの再設計が必要
  2. 次のボトルネックは C7 ULTRA 内部

    • alloc (7.66%) + free (3.50%) + refill (1.78%) = 12.94%
    • このうち refill (1.78%) が新規ボトルネック
  3. Refill パスが visible に

    • C7 ULTRA は page を「必要に応じて allocate」
    • refill 呼び出しが所々で発生し、tiny_c7_ultra_page_of が呼ばれている

目的

C7 ULTRA refill パスを最適化し、tiny_c7_ultra_page_of の 1.78% を削減

期待効果:

  • refill path 削減で 0.5-1% の削減
  • 全体スループット +0.5-2M ops/s30M → 30.5-32M ops/s

現状の C7 ULTRA refill 構造

TLS キャッシュ管理

C7 ULTRA は以下の構造を持つ:

typedef struct TinyC7UltraBox {
    // TLS freelistalloc pop 用)
    void* freelist[128];
    uint16_t count;

    // Segment 情報free で学習)
    uintptr_t seg_base, seg_end;
    tiny_c7_ultra_segment_t* cached_segment;

} TinyC7UltraBox;

Refill のトリガー

  1. Alloc 側:

    • TLS freelist が empty → refill_cold パスへ
    • segment から新しいページを割り当て
    • 128 個のブロックを freelist に詰める
  2. Retire 側:

    • freelist が full → retire_cold へ
    • ページを segment に返す

tiny_c7_ultra_page_of の役割

refill/retire 時に「ページを特定するため」に呼ばれる:

tiny_c7_ultra_page_meta_t* tiny_c7_ultra_page_of(void* p,
                                             tiny_c7_ultra_segment_t** out_seg,
                                             uint32_t* out_page_idx) {
    tiny_c7_ultra_segment_t* seg = tiny_c7_ultra_segment_from_ptr(p);
    if (!seg) return NULL;

    // Offset 計算と page index 取得
    uintptr_t offset = (uintptr_t)p - (uintptr_t)seg->base;
    uint32_t idx = (uint32_t)(offset / seg->page_size);

    // Bounds check
    if (idx >= seg->num_pages) return NULL;

    return &seg->pages[idx];
}

cost breakdown:

  • tiny_c7_ultra_segment_from_ptr(): O(1) ptr lookup
  • offset 計算: 固定コスト1-2 cycles
  • page_size division: 可変seg->page_size がキャッシュマイス可能)
  • bounds check: 1-2 cycles

最適化候補

Option 1: Page size を固定に(最大効果)

現状:

size_t page_size;  // seg ごとに異なる可能性
uint32_t idx = (uint32_t)(offset / seg->page_size);  // division

問題: seg->page_size が毎回参照 → cache line miss 可能性

最適化案:

  • TINY_C7_ULTRA_PAGE_SIZE を macro 定義64KiB 固定と仮定)
  • division → right shift に最適化(offset >> PAGE_SHIFT

期待: division 命令削減で 0.1-0.2% 削減

条件: C7 ULTRA segment の page_size が常に一定であることを確認


Option 2: Segment learning を alloc 側に移動(中程度効果)

現状:

  • free 時に segment を学習initial miss
  • その後 free はキャッシュされた seg_base/seg_end でチェック

提案:

  • alloc refill 時に segment を学習/cache
  • refill が segment を既に知っている → segment_from_ptr が不要に

期待: refill パスで segment_from_ptr call 削減 → 0.2-0.3%


Option 3: Page lookup の TLS cache小程度効果

提案:

  • 直前に lookup した page を TLS に cache
  • 同じページに対する refill 呼び출しなら cache hit

期待: 0.1% 程度alloc batch が小さいため)


実装計画(推奨順)

Phase REFILL-OPT-1a: Page Size Macro 化

  1. 確認:

    • C7 ULTRA segment の page_size 値を記録
    • 常に 64KiBまたは固定値か確認
  2. 実装:

    • TINY_C7_ULTRA_PAGE_SIZE macro を定義
    • tiny_c7_ultra_page_of で offset >> TINY_C7_ULTRA_PAGE_SHIFT に変更
    • tiny_c7_ultra_segment_t から page_size を削除optional
  3. テスト:

    • Mixed bench: 29.5-32M ops/s 範囲で確認
    • SEGV/assert なし
  4. 計測:

    • perf で tiny_c7_ultra_page_of self% が 1.78% → 1.5% 以下か確認

Phase REFILL-OPT-1b: Segment Learning in Alloc

  1. 実装:

    • tiny_c7_ultra_alloc_refill で segment を学習して cache
    • tiny_c7_ultra_segment_from_ptr 呼び出し削減
  2. テスト同様


リスク評価

リスク 確率 対策
page_size が可変 確認 phase で判定、fallback 用 code keep
segment cache miss TLS cache 容量確保
allocation pattern 変化 multi-thread test で確認

成功条件

  • Build 成功、warning なし
  • Mixed bench で SEGV/assert なし
  • Throughput 回帰なし(≥ 2%
  • tiny_c7_ultra_page_of self% が 1.5% 以下

参考資料

  • PERF_ULTRA_REBASE_4.md: 詳細計測結果
  • TINY_C7_ULTRA_DESIGN.md: C7 ULTRA 設計概要
  • docs/analysis/ALLOC_GATE_ANALYSIS.md: Gate 分析