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>
This commit is contained in:
105
CURRENT_TASK.md
105
CURRENT_TASK.md
@ -481,35 +481,98 @@ alloc 側に TLS pop を追加して統合し、完全な alloc/free サイク
|
||||
|
||||
---
|
||||
|
||||
## 次フェーズ候補(未決定、検討中)
|
||||
## Phase PERF-ULTRA-REBASE-1 実施完了 (2025-12-11)
|
||||
|
||||
### 選択肢 1: C5 ULTRA への展開
|
||||
**目的**: C4-C7 ULTRA を全て有効にした状態での CPU ホットパス計測
|
||||
|
||||
**根拠**: Phase 4-4 後の stats で C5 が新しい最大 legacy share(仮定: ~68K)
|
||||
**計測条件**:
|
||||
- ENV: HAKMEM_TINY_C4/C5/C6/C7_ULTRA_FREE_ENABLED=1(全て ON)
|
||||
- v6/v5/v4/free-front-v3 は OFF(研究箱)
|
||||
- ワークロード: Mixed 16-1024B, 10M cycles, ws=8192
|
||||
- Throughput: 31.61M ops/s
|
||||
|
||||
**リスク**:
|
||||
- C5 ブロックサイズ小さい → TLS cache で L1 eviction リスク
|
||||
- v6 経験: alloc/free 統合型でも -12% だったため、単純な拡張では効果限定か
|
||||
**ホットパス分析結果** (allocator 内部, self%):
|
||||
|
||||
**提案**:
|
||||
- C5 ULTRA の TLS capacity を小さく設定(64 blocks vs C6 の 128)
|
||||
- ENV で opt-in(HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=0)
|
||||
- Mixed で +2-3% 期待値設定(C6 の +4.9% より低く見積もる)
|
||||
| 順位 | 関数/パス | self% | 分類 |
|
||||
|------|----------|-------|------|
|
||||
| 🔴 **#1** | **C7 ULTRA alloc** | **7.66%** | ← **新しい最大ボトルネック** |
|
||||
| #2 | C4-C7 ULTRA free群 | 5.41% | alloc-free cycle |
|
||||
| #3 | so_alloc系 (v3 backend) | 3.60% | 中規模alloc |
|
||||
| #4 | page_of/segment判定 | 2.74% | ptr解決 |
|
||||
| #5 | gate/front前段 | 2.51% | ✅改善済み |
|
||||
| #6 | so_free系 | 2.47% | - |
|
||||
| #7 | ss_map_lookup | 0.79% | ✅大幅改善済み |
|
||||
|
||||
### 選択肢 2: Tiny Alloc Hotpath 最適化
|
||||
**重要な発見**:
|
||||
1. **C7 ULTRA alloc が明確な最大ボトルネック** - gate/front や header はもう十分薄い
|
||||
2. **header書き込みが不可視** (< 0.17%) - ULTRA経路での削減効果が出ている
|
||||
3. **gate/front は既に許容範囲** (2.51%) - 以前のフェーズより改善済み
|
||||
|
||||
**根拠**: 残存 legacy (129,623) に C0-C4 が含まれている
|
||||
**分析結論**:
|
||||
- v6/v5/v4 のような新世代追加ではなく、「既に当たりが出ている C7/C4/C5/C6 ULTRA 内部を薄くする」フェーズへ転換すべき
|
||||
- C7 ULTRA alloc の 7.66% を 5-6% に削れば、全体で 2-3% の効果が期待できる
|
||||
|
||||
**提案**:
|
||||
- tiny_alloc_gate_fast / malloc_tiny_fast の branch 削減
|
||||
- header validation パスの最適化
|
||||
- tiny route classification の ENV overhead 削減
|
||||
**詳細**: `docs/analysis/TINY_CPU_HOTPATH_USERLAND_ANALYSIS.md` 参照
|
||||
|
||||
**期待値**: +2-3% (indirect path 最適化のため限定的)
|
||||
---
|
||||
|
||||
### 次の判断ポイント
|
||||
## Phase PERF-ULTRA-ALLOC-OPT-1 計画(実装予定)
|
||||
|
||||
1. Stats 実行後に C5 legacy が確定したら → 選択肢 1 or 2 を決定
|
||||
2. V6 との統合(alloc 連携で v6 も改善する?)の検討
|
||||
3. Pool v1 の free hotpath 最適化(Phase 4 の「残存」だった pool_v1_fast の高速化)
|
||||
**目的**: C7 ULTRA alloc(7.66%)の内部最適化による alloc パス高速化
|
||||
|
||||
**ターゲット**: `tiny_c7_ultra_alloc()` の hot path を直線化
|
||||
|
||||
**実装施策**:
|
||||
1. **TLS ヒットパスの直線化**
|
||||
- env check / snapshot 取得が残っていないか確認
|
||||
- fast path を完全に直線化(分岐最小化)
|
||||
2. **TLS freelist レイアウト最適化**
|
||||
- 1 cache line に収まるか確認
|
||||
- alloc ホットデータ(freelist[], count)の配置最適化
|
||||
3. **segment/page_meta アクセスの確認**
|
||||
- segment learning / page_meta access が本当に slow path だけか確認
|
||||
- hot path に余分なメモリアクセスがないか確認
|
||||
|
||||
**計測戦略**:
|
||||
- C7-only と Mixed 両方の A/B テスト(enabler: HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1)
|
||||
- perf 計測で self% が 7.66% → 5-6% まで落ちるか確認
|
||||
- throughput 改善量を測定
|
||||
|
||||
**期待値**: alloc パスで 5-10% の削減
|
||||
|
||||
**次ステップ**: 実装完了後、perf 再計測で効果を検証
|
||||
|
||||
---
|
||||
|
||||
## 次フェーズ候補(決定保留中)
|
||||
|
||||
### 実装予定フェーズ
|
||||
|
||||
1. **Phase PERF-ULTRA-ALLOC-OPT-1** (即座実装)
|
||||
- C7 ULTRA alloc 内部最適化
|
||||
- 目標: 7.66% → 5-6%
|
||||
- 期待: 全体で 2-3% 改善
|
||||
|
||||
2. **Phase PERF-ULTRA-ALLOC-OPT-2** (後続)
|
||||
- C4-C7 ULTRA free群(5.41%)の軽量化
|
||||
- page_of / segment判定との連携最適化
|
||||
|
||||
### 研究箱(後回し、当面は OFF)
|
||||
|
||||
- **C3/C2 ULTRA**: legacy 小さい(4% 未満)のに TLS 増加で L1 汚染リスク
|
||||
- **v6/v5/v4 拡張**: 既存 v1/pool より大幅に遅く、新世代追加は現段階では回帰誘発
|
||||
- **FREE-FRONT-V3-2**: 以前 -4% 回帰があったため、ULTRA 整備後に再検討
|
||||
|
||||
---
|
||||
|
||||
## 実装ポリシー変換(重要)
|
||||
|
||||
### これまで(フェーズ 4-4 まで)
|
||||
- 新しい箱や世代(v4/v5/v6/free-front-v3 等)を増やす
|
||||
- 当たりが出たら本線化する
|
||||
|
||||
### 今後(PERF-ULTRA-ALLOC-OPT 以降)
|
||||
- **既に当たりが出ている箱(C4-C7 ULTRA)の中身を細かく削る**
|
||||
- 新世代追加は避ける(L1 キャッシュ汚染、複雑度増加のリスク)
|
||||
- hotpath 分析 → ピンポイント最適化のサイクルを回す
|
||||
|
||||
|
||||
321
docs/analysis/PERF_ULTRA_ALLOC_OPT_1_PLAN.md
Normal file
321
docs/analysis/PERF_ULTRA_ALLOC_OPT_1_PLAN.md
Normal file
@ -0,0 +1,321 @@
|
||||
# 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/s(31.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 ヒットパスの直線化
|
||||
|
||||
**確認項目**:
|
||||
|
||||
```c
|
||||
// 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 チェックのみ
|
||||
- ユーザーポインタ計算は単純な演算のみ
|
||||
|
||||
**実装例**:
|
||||
|
||||
```c
|
||||
// 最適化前の可能性が高い形
|
||||
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 レイアウト最適化
|
||||
|
||||
**確認項目**:
|
||||
|
||||
```c
|
||||
// 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 line(64B)に収まるか
|
||||
- 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 data(count)が先頭に配置されているか
|
||||
- 現行は freq[capacity/count] が後ろ
|
||||
- → count を先頭に移動すれば、alloc pop 時の cache line access 1 本(count チェック)で済む
|
||||
|
||||
- [ ] seg_base / seg_end は確実に slow path(free 時の segment learning)か
|
||||
- → alloc は seq_base を参照しない → hot path から外すべき
|
||||
|
||||
**実装例**:
|
||||
|
||||
```c
|
||||
// 最適化後(期待値)
|
||||
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 アクセスの確認
|
||||
|
||||
**確認項目**:
|
||||
|
||||
```c
|
||||
// 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 path(unlikely)として外出しされているか
|
||||
- → 初回 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: ベースライン(実装前)
|
||||
|
||||
```bash
|
||||
# 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 回計測して平均を取る:
|
||||
|
||||
```bash
|
||||
# 最適化後の計測(同じコマンド)
|
||||
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/s(31.6M → 33-35M ops/s)
|
||||
|
||||
### Phase 2: 詳細分析
|
||||
|
||||
```bash
|
||||
# 各関数の 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 チェックの配置
|
||||
|
||||
```c
|
||||
// ❌ 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 再利用
|
||||
|
||||
```c
|
||||
// ❌ 複数回 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. 構造体レイアウトの確認
|
||||
|
||||
```c
|
||||
// 実装後、以下で 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 計画」
|
||||
|
||||
@ -50,3 +50,63 @@
|
||||
- UF-2: ULTRA TLS freelist を実装(C7 ページ 1 枚を TLS で握る。同一スレッドのみ)。C7 ページ供給は当面 v3/v4 経由。
|
||||
- UF-3: C7UltraSegmentBox を実装し、ptr→segment mask でヘッダレス free に寄せる(セグメント 1 枚のみでも可)。
|
||||
- UF-4: C7 ULTRA header light を研究箱として追加し、ON/OFF A/B(Mixed / C7-only 両方)で評価する。
|
||||
|
||||
---
|
||||
|
||||
## Phase PERF-ULTRA-ALLOC-OPT-1: C7 ULTRA alloc 内部最適化(実装予定)
|
||||
|
||||
### 背景(Phase PERF-ULTRA-REBASE-1 の発見)
|
||||
|
||||
2025-12-11 の perf 計測(C4-C7 ULTRA 全て ON)で以下が判明:
|
||||
|
||||
**ホットパス分析結果** (allocator 内部, self%):
|
||||
- **C7 ULTRA alloc: 7.66%** ← **新しい最大ボトルネック**
|
||||
- C4-C7 ULTRA free群: 5.41%
|
||||
- gate/front前段: 2.51% ← **既に十分薄い**
|
||||
- header: < 0.17% ← **ULTRA 経路での削減効果が出ている**
|
||||
|
||||
### 結論
|
||||
|
||||
**v6/v5/v4 のような新世代追加ではなく、既に当たりが出ている ULTRA 内部を薄くする方針に転換**。
|
||||
|
||||
- v6/v5 の C5/C4 拡張は -12〜33% の大幅回帰を招いた
|
||||
- header や gate/front は既に改善済み(許容範囲)
|
||||
- **C7 ULTRA alloc の 7.66% を 5-6% に削れば、全体で 2-3% の効果が期待できる**
|
||||
|
||||
### 実装施策
|
||||
|
||||
**ターゲット**: `tiny_c7_ultra_alloc()` の hot path を直線化
|
||||
|
||||
1. **TLS ヒットパスの直線化**
|
||||
- env check が残っていないか確認(lazy init 後は ENV 参照すべきではない)
|
||||
- snapshot 取得が hot path に含まれていないか確認
|
||||
- fast path を完全に直線化(分岐最小化)
|
||||
|
||||
2. **TLS freelist レイアウト最適化**
|
||||
- freelist[], count などのホットデータが 1 cache line に収まるか確認
|
||||
- alloc ホットデータ(freelist[], count)の配置を L1 キャッシュ友好的に再配置
|
||||
|
||||
3. **segment / page_meta アクセスの確認**
|
||||
- segment learning / page_meta access が本当に slow path(キャッシュミス時)だけか確認
|
||||
- hot path に余分なメモリアクセスが混入していないか確認
|
||||
|
||||
### 計測戦略
|
||||
|
||||
**A/B テスト**:
|
||||
- C7-only(1024B固定)と Mixed(16-1024B)の両方で計測
|
||||
- enabler: HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1
|
||||
|
||||
**perf 計測**:
|
||||
- 最適化前後で `perf report --stdio` により self% が 7.66% → 5-6% まで落ちるか確認
|
||||
- throughput 改善量(ops/s)を測定
|
||||
|
||||
### 期待値
|
||||
|
||||
- **alloc パス**: 5-10% の削減(self% 2% 削減で全体効果 2-3%)
|
||||
- **全体 Mixed throughput**: +2-3M ops/s(31.6M ops/s → 33-35M ops/s 想定)
|
||||
|
||||
### 次ステップ
|
||||
|
||||
1. 実装完了後、perf 再計測で効果を検証
|
||||
2. self% が 5-6% に達したら次フェーズ(C4-C7 ULTRA free群 5.41% の軽量化)へ
|
||||
3. それ以上の改善は narrow point(page_of/segment 判定, so_alloc系)の検討が必要
|
||||
|
||||
@ -123,3 +123,117 @@ Throughput: **12.39M ops/s**(DEBUG/-O0 相当)
|
||||
- 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` は 2–3% まで微増(外れ時のフォールバック分)。
|
||||
- 所感: C7 v3 free の Superslab lookup 往復をほぼ除去でき、目標の +5〜10% に収まる結果。fast path 判定の TLS 走査が新たなホットスポットだが、現状コストは lookup より低く許容範囲。
|
||||
|
||||
## Phase PERF-ULTRA-REBASE-1 Results (2025-12-11 19:43:49)
|
||||
|
||||
### 計測環境
|
||||
- **日時**: 2025-12-11 19:43:49
|
||||
- **ワークロード**: Mixed 16-1024B, ws=8192, iters=10,000,000
|
||||
- **ENV設定**:
|
||||
- `HAKMEM_TINY_C7_ULTRA_FREE_ENABLED=1`
|
||||
- `HAKMEM_TINY_C6_ULTRA_FREE_ENABLED=1`
|
||||
- `HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=1`
|
||||
- `HAKMEM_TINY_C4_ULTRA_FREE_ENABLED=1`
|
||||
- その他 ULTRA 以外のフラグは OFF(v6/v4/v5/free-front-v3 等)
|
||||
- **perf コマンド**: `perf record -F 5000 --call-graph dwarf -e cycles:u`
|
||||
- **Throughput**: **31.61M ops/s**
|
||||
- **Samples**: 1842 samples, 約1.36B cycles
|
||||
|
||||
### perf report 主要関数 self% トップ20
|
||||
1. **free**: 25.48%(libc wrapper/ベンチ由来)
|
||||
2. **main**: 23.60%(ベンチマークハーネス)
|
||||
3. **malloc**: 21.13%(libc wrapper/ベンチ由来)
|
||||
4. **tiny_c7_ultra_alloc**: 7.66%
|
||||
5. **tiny_c7_ultra_free**: 3.50%
|
||||
6. **so_free**: 2.47%
|
||||
7. **so_alloc_fast**: 2.39%
|
||||
8. **tiny_c7_ultra_page_of**: 1.78%
|
||||
9. **classify_ptr**: 1.15%
|
||||
10. **tiny_c7_ultra_segment_from_ptr**: 0.96%
|
||||
11. **tiny_front_v3_lut_lookup**: 0.91%
|
||||
12. **ss_map_lookup**: 0.79%
|
||||
13. **tiny_c5_ultra_free_fast**: 0.69%
|
||||
14. **hak_free_at**: 0.68%
|
||||
15. **tiny_c6_ultra_free_fast**: 0.54%
|
||||
16. **tiny_guard_is_enabled**: 0.45%
|
||||
17. **tiny_c6_ultra_free_tls**: 0.34%
|
||||
18. **tiny_heap_page_becomes_empty**: 0.23%
|
||||
19. **tiny_c4_ultra_free_fast**: 0.17%
|
||||
20. **tiny_c5_ultra_free_tls**: 0.17%
|
||||
|
||||
### カテゴリ別集計
|
||||
- **ベンチマーク関連(main + free + malloc wrapper)**: 70.21%
|
||||
- **C4-C7 ULTRA free関数群の合計**: 5.41%
|
||||
- tiny_c7_ultra_free: 3.50%
|
||||
- tiny_c5_ultra_free_fast: 0.69%
|
||||
- tiny_c6_ultra_free_fast: 0.54%
|
||||
- tiny_c6_ultra_free_tls: 0.34%
|
||||
- tiny_c4_ultra_free_fast: 0.17%
|
||||
- tiny_c5_ultra_free_tls: 0.17%
|
||||
- **C7 ULTRA alloc**: 7.66%
|
||||
- **so_alloc系(v3 backend alloc)**: 3.60%
|
||||
- so_alloc_fast: 2.39%
|
||||
- so_alloc: 1.21%
|
||||
- **so_free系(v3 backend free)**: 2.47%
|
||||
- **gate/front関連**: 2.51%
|
||||
- classify_ptr: 1.15%
|
||||
- tiny_front_v3_lut_lookup: 0.91%
|
||||
- tiny_guard_is_enabled: 0.45%
|
||||
- **page_of/segment判定**: 2.74%
|
||||
- tiny_c7_ultra_page_of: 1.78%
|
||||
- tiny_c7_ultra_segment_from_ptr: 0.96%
|
||||
- **ss_map_lookup(Superslab判定)**: 0.79%
|
||||
- **hak_free_at**: 0.68%
|
||||
- **tiny_heap_page_becomes_empty**: 0.23%
|
||||
|
||||
### 分析コメント
|
||||
1. **C7 ULTRA alloc が最大ホットスポット(7.66%)**
|
||||
- C7 ULTRA の allocate パスが allocator 内で最も重いボトルネック
|
||||
- 次点は ULTRA free 群(5.41%)だが、alloc が約1.4倍重い
|
||||
|
||||
2. **so_alloc系(v3 backend)が3.60%で続く**
|
||||
- C7 v3 の backend alloc 処理が依然として可視
|
||||
- so_free は2.47%でバランス良好
|
||||
|
||||
3. **page_of/segment判定が2.74%**
|
||||
- tiny_c7_ultra_page_of(1.78%)とsegment_from_ptr(0.96%)の合計
|
||||
- ULTRA free内でのptr→page/segment解決コストが目立つ
|
||||
|
||||
4. **gate/front前段は2.51%に留まる**
|
||||
- classify_ptr(1.15%)、LUT lookup(0.91%)、guard判定(0.45%)
|
||||
- 以前のフェーズより改善されており、現時点では相対的に軽い
|
||||
|
||||
5. **ss_map_lookup は0.79%まで低下**
|
||||
- TF3 + PTR_FAST_CLASSIFY の効果で Superslab lookup が大幅減
|
||||
- 依然残っているが、優先度は下がった
|
||||
|
||||
6. **header書き込みが不可視**
|
||||
- tiny_region_id_write_header が上位20に入っていない(< 0.17%)
|
||||
- ULTRA経路では header 書き込みコストが削減されている可能性
|
||||
|
||||
### 次の候補箱(ボトルネック優先順位)
|
||||
1. **最優先: C7 ULTRA alloc(7.66%)**
|
||||
- tiny_c7_ultra_alloc の内部最適化が最大の削減ポテンシャル
|
||||
- キャッシュヒット率向上、TLS構造簡素化、分岐削減などを検討
|
||||
|
||||
2. **第2優先: C4-C7 ULTRA free群(5.41%)**
|
||||
- 特に tiny_c7_ultra_free(3.50%)が中心
|
||||
- page_of/segment判定(2.74%)との重複があるため、ptr解決の高速化が有効
|
||||
|
||||
3. **第3優先: so_alloc系 backend(3.60%)**
|
||||
- C7 v3 の backend alloc 処理の軽量化
|
||||
- fast path のインライン化や TLS キャッシュ強化
|
||||
|
||||
4. **第4優先: page_of/segment判定(2.74%)**
|
||||
- ptr→page/segment 解決の最適化
|
||||
- TLS キャッシュや LUT ベースの高速化を検討
|
||||
|
||||
5. **監視対象: gate/front前段(2.51%)**
|
||||
- 現状は許容範囲だが、さらなる改善余地あり
|
||||
- classify_ptr の fast path 強化や LUT の効率化
|
||||
|
||||
### 所感
|
||||
- **C7 ULTRA alloc が明確な最大ボトルネック**として浮上。次のフェーズでは alloc パスの内部最適化(TLS キャッシュヒット率向上、構造簡素化、分岐削減)に注力すべき。
|
||||
- ULTRA free 群も5.41%と無視できないが、alloc が約1.4倍重いため、alloc を先に削るのが効率的。
|
||||
- gate/front 前段は以前のフェーズより改善されており、現時点での優先度は下がった。
|
||||
- header 書き込みが上位20に入っていないのは、ULTRA 経路での削減効果が出ている可能性がある。
|
||||
|
||||
Reference in New Issue
Block a user