Files
hakmem/docs/analysis/PERF_ULTRA_ALLOC_OPT_1_PLAN.md
Moe Charm (CI) b381219a68 Phase PERF-ULTRA-REBASE-1 計測完了 + PERF-ULTRA-ALLOC-OPT-1 計画策定
## 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>
2025-12-11 20:05:09 +09:00

9.6 KiB
Raw Blame History

Phase PERF-ULTRA-ALLOC-OPT-1 実装計画

フェーズ名: Phase PERF-ULTRA-ALLOC-OPT-1: C7 ULTRA alloc 内部最適化

目的: C7 ULTRA alloc現在 7.66% self%)の hot path を直線化し、5-6% まで削減

期待効果: 全体 Mixed throughput で +2-3M ops/s31.6M ops/s → 33-35M ops/s


背景

Phase PERF-ULTRA-REBASE-1 の発見

2025-12-11 の perf 計測結果C4-C7 ULTRA 全て ON, Mixed 16-1024B, 10M cycles:

順位 関数 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% の大幅回帰C5/C4 対応で失敗)
  • gate/front や header はもう改善の余地が少ない
  • C7 ULTRA alloc の 7.66% を 5-6% に削れば全体効果 2-3%

実装対象ファイル

主要ファイル

  • core/box/tiny_c7_ultra_free_box.h

    • TinyC7UltraFreeTLS 構造体定義
    • tiny_c7_ultra_alloc_fast() / tiny_c7_ultra_alloc_cold() の宣言
  • core/box/tiny_c7_ultra_free_box.c

    • tiny_c7_ultra_alloc_fast() 実装(メイン最適化対象)
    • TLS context の定義と初期化
  • core/front/malloc_tiny_fast.h

    • tiny_c7_ultra_alloc() の呼び出し箇所
    • alloc dispatcher からの pop ロジック

参照/確認ファイル

  • core/box/tiny_c7_ultra_free_env_box.h

    • tiny_c7_ultra_free_enabled() - ENV gate の状態確認
  • core/link_stubs.c / core/hakmem.c

    • 起動時の ENV 初期化タイミング確認

実装施策

1. TLS ヒットパスの直線化

確認項目:

// tiny_c7_ultra_alloc_fast() のコード流
TinyC7UltraFreeTLS* ctx = tiny_c7_ultra_free_tls();
if (ctx->count > 0) {
    void* base = ctx->freelist[--ctx->count];
    return tiny_base_to_user_inline(base);
}

チェック項目:

  • tiny_c7_ultra_free_enabled() が hot path に含まれていないか
    • → lazy init 後は ENV 参照が不要。guard は不要。
    • → if (!tiny_c7_ultra_free_enabled()) return NULL; のような early guard は削除
  • tiny_c7_ultra_free_tls() が毎回呼ばれているか
    • → TLS pointer cache で 1 回だけ取得し、ローカル変数に格納
    • → 複数回アクセスなら cache 再利用
  • hot path に条件分岐が何個あるか(目標: 1-2個
    • count > 0 チェックのみ
    • ユーザーポインタ計算は単純な演算のみ

実装例:

// 最適化前の可能性が高い形
void* tiny_c7_ultra_alloc_fast(void) {
    if (!tiny_c7_ultra_free_enabled()) return NULL;
    TinyC7UltraFreeTLS* ctx = tiny_c7_ultra_free_tls();
    if (ctx == NULL) return NULL;  // ← 不要な null check
    if (ctx->count == 0) return NULL;
    ...
}

// 最適化後expected
void* tiny_c7_ultra_alloc_fast(void) {
    // tiny_c7_ultra_free_enabled() check は呼び出し側で済ませる
    // malloc_tiny_fast.h で if (tiny_c7_ultra_free_enabled()) { tiny_c7_ultra_alloc_fast(); } の形)
    TinyC7UltraFreeTLS* ctx = __thread_local_tls_c7;  // 直接 TLS access
    if (likely(ctx->count > 0)) {
        void* base = ctx->freelist[--ctx->count];
        return tiny_base_to_user_inline(base);
    }
    return NULL;
}

2. TLS freelist レイアウト最適化

確認項目:

// TinyC7UltraFreeTLS 構造体の定義確認
typedef struct TinyC7UltraFreeTLS {
    void* freelist[TINY_C7_ULTRA_FREE_CAP];  // 128 * 8B = 1024B
    uint8_t count;                           // + 1B = 1025B
    uintptr_t seg_base, seg_end;             // + 16B = 1041B
} TinyC7UltraFreeTLS;

チェック項目:

  • freelist と count が 1 cache line64Bに収まるか

    • freelist[TINY_C7_ULTRA_FREE_CAP] サイズを確認(デフォルト 128 要素 = 1024B
    • → 1024B は L1 キャッシュ(通常 32-64KBを超過しているので、count のみが hot
    • → count アクセスは cache line 1 本で十分
    • → freelist アクセスは cache misses が避けられないalloc pop は 128 個のブロックを引き出すのに 1 個アクセスだから許容)
  • alloc hot datacountが先頭に配置されているか

    • 現行は freq[capacity/count] が後ろ
    • → count を先頭に移動すれば、alloc pop 時の cache line access 1 本count チェック)で済む
  • seg_base / seg_end は確実に slow pathfree 時の segment learning

    • → alloc は seq_base を参照しない → hot path から外すべき

実装例:

// 最適化後(期待値)
typedef struct TinyC7UltraFreeTLS {
    // Hot path 用64B以内想定
    uint16_t count;                          // ← alloc pop で必須
    uint8_t pad;
    void* freelist[128];                     // ← large block, only used for pop

    // Cold path 用segment learning など)
    uintptr_t seg_base, seg_end;             // free 時のみ
} TinyC7UltraFreeTLS;

3. segment / page_meta アクセスの確認

確認項目:

// tiny_c7_ultra_free_fast() の segment learning ロジック確認
if (unlikely(ctx->seg_base == 0)) {
    SuperSlab* ss = ss_fast_lookup(base);
    ctx->seg_base = (uintptr_t)ss;
    ctx->seg_end  = ctx->seg_base + (1u << ss->lg_size);
}

チェック項目:

  • segment learning は cold pathunlikelyとして外出しされているか

    • → 初回 free で 1 回だけ実行
    • → 以降のすべての free は segment cached チェックで済む
    • → alloc は segment を参照しない
  • alloc hot path に page_meta access が混入していないか

    • → alloc は count チェックと base pop だけ
    • → page_meta は free 側のみで十分
  • ss_fast_lookup() が cache miss 時のみか

    • → segment learning 時unlikelyのみ
    • → これは現状で十分1 回だけ)

計測戦略

Phase 0: ベースライン(実装前)

# C7-only bench
HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1 \
perf record -F 5000 --call-graph dwarf -e cycles:u \
./bench_allocators_hakmem C7 1000000 400 1

# Mixed bench
HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1 HAKMEM_FREE_PATH_STATS=1 \
perf record -F 5000 --call-graph dwarf -e cycles:u \
./bench_random_mixed_hakmem 10000000 8192 1

# perf report で self% を記録
perf report --stdio | grep -A 5 "tiny_c7_ultra_alloc"

期待値: C7 ULTRA alloc の self% = 7.66%(ベースライン)

Phase 1: 各施策の実装と計測

実装後、同じ条件で 3 回計測して平均を取る:

# 最適化後の計測(同じコマンド)
for i in 1 2 3; do
    HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1 \
    perf record -F 5000 --call-graph dwarf -e cycles:u \
    ./bench_random_mixed_hakmem 10000000 8192 1
    perf report --stdio > perf_opt_run$i.txt
done

目標:

  • self% = 5-6%(削減幅 2-3%
  • throughput = +2-3M ops/s31.6M → 33-35M ops/s

Phase 2: 詳細分析

# 各関数の self% を比較表にまとめる
# - tiny_c7_ultra_alloc_fast vs tiny_c7_ultra_alloc_cold
# - ss_fast_lookup / segment learning の slow path confirmation
# - freelist access パターン

検証チェックリスト

実装完了時、以下をすべて確認:

  • コンパイル成功warning なし)
  • リンク成功
  • C7-only bench で SEGV/assert なし
  • Mixed bench で SEGV/assert なし
  • perf 計測で self% が 5-6% に達している
  • throughput が +2-3M ops/s 改善
  • 各関数の分岐数が max 2-3直線化目標
  • TLS access が 1 回だけcache 再利用)

実装時の注意点

1. ENV チェックの配置

// ❌ Hot path 内で ENV check
if (tiny_c7_ultra_free_enabled()) {  // ← hot path で毎回?
    ...
}

// ✅ 呼び出し側malloc_tiny_fast.h dispatcherでチェック
if (tiny_c7_ultra_free_enabled()) {
    void* p = tiny_c7_ultra_alloc_fast();
    if (p) return p;
}

2. TLS cache 再利用

// ❌ 複数回 TLS access
TinyC7UltraFreeTLS* ctx = tiny_c7_ultra_free_tls();
if (ctx->count > 0) {
    void* base = ctx->freelist[--ctx->count];  // ← 1回目
    ...
}
if (ctx->count > 0) {  // ← 2回目の access
    ...
}

// ✅ ローカル変数に cache
TinyC7UltraFreeTLS* ctx = tiny_c7_ultra_free_tls();
uint16_t count = ctx->count;
if (likely(count > 0)) {
    void* base = ctx->freelist[--count];
    ctx->count = count;
    return tiny_base_to_user_inline(base);
}

3. 構造体レイアウトの確認

// 実装後、以下で hot field 配置を確認
// (gdb) p sizeof(TinyC7UltraFreeTLS)
// (gdb) p &ctx->count, &ctx->freelist
// → count が freelist より先頭にあることを確認

次フェーズへのつなぎ

このフェーズの成功条件

  • self% が 5-6% に低下
  • throughput が +2-3M ops/s 達成
  • 新しい bottleneck が浮上page_of/segment 判定, so_alloc など)

Phase 2 の候補(自動昇格)

self% が 5-6% に達したら、次は C4-C7 ULTRA free群5.41% の軽量化を検討:

  • free side のTLS push パス直線化
  • page_of / segment 判定との連携最適化

参考資料

  • ホットパス分析: docs/analysis/TINY_CPU_HOTPATH_USERLAND_ANALYSIS.md
  • C7 ULTRA 設計: docs/analysis/TINY_C7_ULTRA_DESIGN.md
  • 全体方針: CURRENT_TASK.md 「Phase PERF-ULTRA-ALLOC-OPT-1 計画」