Files
hakmem/docs/analysis/FREE_LEGACY_PATH_ANALYSIS.md

307 lines
12 KiB
Markdown
Raw Normal View History

Phase FREE-LEGACY-OPT-4-1: Legacy per-class breakdown analysis ## 目的 Legacy fallback 49.2% の内訳を per-class で分析し、最も Legacy を使用しているクラスを特定。 ## 実装内容 1. FreePathStats 構造体の拡張 - legacy_by_class[8] フィールドを追加(C0-C7 の Legacy fallback 内訳) 2. デストラクタ出力の更新 - [FREE_PATH_STATS_LEGACY_BY_CLASS] 行を追加し、C0-C7 の内訳を出力 3. カウンタの散布 - free_tiny_fast() の Legacy fallback 経路で legacy_by_class[class_idx] をインクリメント - class_idx の範囲チェック(0-7)を実施 ## 測定結果(Mixed 16-1024B) **測定安定性**: 完全に安定(3 回とも同一の値、決定的測定) Legacy per-class 内訳: - C0: 0 (0.0%) - C1: 0 (0.0%) - C2: 8,746 (3.3% of legacy) - C3: 17,279 (6.5% of legacy) - C4: 34,727 (13.0% of legacy) - C5: 68,871 (25.8% of legacy) - C6: 137,319 (51.4% of legacy) ← 最大シェア - C7: 0 (0.0%) 合計: 266,942 (49.2% of total free calls) ## 分析結果 **最大シェアクラス**: C6 (513-1024B) が Legacy の 51.4% を占める **理由**: - Mixed 16-1024B では C6 サイズのアロケーションが多い - C7 ULTRA は C7 専用で C6 は未対応 - v3/v4 も C6 をカバーしていない - Route 設定で C6 は Legacy に直接落ちている ## 次のアクション Phase FREE-LEGACY-OPT-4-2 で C6 クラスに ULTRA-Free lane を実装: - Legacy fallback を 51% 削減(C6 分) - Legacy: 49.2% → 24-27% に改善(半減) - Mixed 16-1024B: 44.8M → 47-48M ops/s 程度(+5-8% 改善) ## 変更ファイル - core/box/free_path_stats_box.h: FreePathStats 構造体に legacy_by_class[8] 追加 - core/box/free_path_stats_box.c: デストラクタに per-class 出力追加 - core/front/malloc_tiny_fast.h: Legacy fallback 経路に per-class カウンタ追加 - docs/analysis/FREE_LEGACY_PATH_ANALYSIS.md: Phase 4-1 分析結果を記録 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 18:04:14 +09:00
# Free Path Legacy Analysis
## 目的
Mixed 161024B で free ≈ 24% の内訳を箱単位で可視化し、次の最適化ターゲットを決定する。
## 現状の free フローBox 単位)
1. **hak_free 入口**
- header 読み取り + magic check
- class_idx 抽出
2. **Route 判定**
- C7 ULTRA checkENV gated
- C7 v3 fast classify check
- v4 fast classify check研究箱
- v6 route check研究箱
- tiny_route_for_class() 呼び出し
- tiny_route_is_heap_kind() 判定
3. **SuperSlab lookup 経路**
- ss_fast_lookup(base)mask-based、~10-15 cycles
- slab_index_for(ss, base)
- Larson cross-thread check
- owner_tid 比較
4. **Route-based dispatch**
- C7 ULTRA → tiny_c7_ultra_free()
- v3 → so_free()
- v6 → small_free_fast_v6()(研究箱)
- TinyHeap v1 → tiny_c7_free_fast_with_meta() / tiny_heap_free_class_fast_with_meta()
- pool v1 → hak_pool_free()
- remote free → tiny_free_remote_box()
5. **Legacy fallback**
- Unified Cache push
- tiny_hot_free_fast()
## Phase FREE-LEGACY-BREAKDOWN-1 測定結果
### Mixed 161024B (1M iterations, ws=400)
**測定安定性**: 完全に安定3 回とも同一の値)
**Run 1, 2, 3全て同一**:
```
[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
```
**平均値と比率**:
| カウンタ | 呼び出し回数 | 比率 (%) | 視覚化 |
|---------|------------|---------|--------|
| **C7 ULTRA fast** | 275,089 | **50.7%** | ██████████████████████████ |
| **Legacy fallback** | 266,942 | **49.2%** | █████████████████████████ |
| pool_v1_fast | 8,081 | 1.5% | █ |
| smallheap_v3_fast | 0 | 0.0% | - |
| tiny_heap_v1_fast | 0 | 0.0% | - |
| super_lookup_called | 0 | 0.0% | - |
| remote_free | 0 | 0.0% | - |
| **Total** | **542,031** | **100.0%** | |
**パフォーマンス**: 平均 44.77M ops/s3 回測定: 44.68M, 44.93M, 44.71M
**分析**:
- **完全な二極化構造**: C7 ULTRA (50.7%) と Legacy fallback (49.2%) でほぼ 1:1
- **C7 ULTRA の成功**: 全体の半分をカバー、このパターンは効果的
- **Legacy の支配**: 残りの半分は依然として legacy 経路に依存
- **pool_v1 は僅少**: 1.5% のみMixed では Tiny サイズが主流)
- **super_lookup は 0**: C7 ULTRA と Legacy はいずれも SuperSlab lookup を経由していない
### C6-heavy mid/smallmid (1M iterations, ws=400)
**測定安定性**: 完全に安定3 回とも同一の値)
**Run 1, 2, 3全て同一**:
```
[FREE_PATH_STATS] total=500108 c7_ultra=0 small_v3=0 v6=0 tiny_v1=0 pool_v1=500099 remote=0 super_lookup=0 legacy_fb=9
```
**平均値と比率**:
| カウンタ | 呼び出し回数 | 比率 (%) | 視覚化 |
|---------|------------|---------|--------|
| **pool_v1_fast** | 500,099 | **100%** (実質) | ████████████████████████████████████████████████████ |
| legacy_fallback | 9 | 0.0% | - |
| その他 | 0 | 0.0% | - |
| **Total** | **500,108** | **100.0%** | |
**パフォーマンス**: 平均 27.03M ops/s3 回測定: 27.07M, 27.05M, 26.96M
**分析**:
- **Pool v1 の完全支配**: 実質 100% が pool_v1 経路を使用
- **シンプルな最適化ターゲット**: pool_v1 経路のみに集中すれば良い
- **legacy_fb=9 の正体**: カウンター設置箇所外の少数例外ケース(無視可能)
### 技術的洞察
#### Mixed の二極化の理由
1. **サイズ分布**: 16-1024B の範囲で、C7 ULTRA が対応するサイズクラスと、Legacy に落ちるサイズクラスが明確に分離
2. **Route 判定**: Fast classify が一部のクラスで機能していない可能性
3. **ENV gating**: 一部のクラスで ENV フラグによって C7 ULTRA が無効化されている
#### C6-heavy の単純性の理由
1. **サイズ範囲**: C6 (257-768B) は完全に pool_v1 の管轄
2. **設計の正しさ**: C6_HEAVY_LEGACY_POOLV1 プロファイルが正しく機能
3. **最適化の明確性**: この経路のみを改善すれば良い
### Legacy fallback の正体
Legacy fallback 49.2% の内訳は不明(クラス単位の分解が必要)。以下が推定される:
- Unified Cache push → `tiny_hot_free_fast()` 経路
- C7 ULTRA に該当しないサイズクラスC0-C6の一部
- Route 判定で C7 ULTRA に到達できなかったケース
**次のアクション**: Phase FREE-LEGACY-OPT-4-1 で Legacy の per-class 分析を実施し、どのクラスが最も Legacy を使用しているか特定する。
## 次フェーズ候補
測定結果を見て以下から選択:
- **FREE-LEGACY-OPT-1**: super_lookup_called が高い場合
→ v6-style TLS ownership check を一部クラスに導入
- **FREE-LEGACY-OPT-2**: pool_v1_fast が高い場合
→ pool v1 の free fast path を局所的に薄くする
- **FREE-LEGACY-OPT-3**: tiny_heap_v1_fast が高い場合
→ Tiny free 側の route/ENV check 削減
- **FREE-LEGACY-OPT-4**: c7_ultra_fast が高い場合
→ C7 ULTRA パターンを他クラスに展開
## 次フェーズ推奨Phase FREE-LEGACY-OPT-4 シリーズ)
### 第一推奨: FREE-LEGACY-OPT-4 (Legacy fallback 削減)
**優先順位**: 最高
**推奨理由**:
- Mixed で Legacy fallback が **49.2%** と最大
- C7 ULTRA パターン (50.7%) の成功を他クラスに展開することで大幅改善が期待できる
**実装計画**:
1. **Phase 4-1**: Legacy の per-class 分析
- `FreePathStats``legacy_by_class[8]` カウンタ追加
- どのクラスC0-C7が Legacy を最も使用しているか特定
2. **Phase 4-2**: 1クラス限定 ULTRA-Free lane の設計・実装
- 対象: 4-1 で特定された最大シェアクラス(仮に C5
- Box 構造:
- C5_ULTRA_FREE_BOX (L0): TLS に `c5_tls_freelist[32]` + `c5_tls_count`
- free 時: `small_tls_owns_ptr_c5()` で range check → TLS push
- TLS full / range 外 → 既存 Legacy へフォールバック
- alloc 側は当面いじらないfree のみ前段キャッシュ)
- ENV: `HAKMEM_TINY_C5_ULTRA_FREE_ENABLED=0`(研究箱)
3. **Phase 4-3**: A/B テスト
- Mixed 16-1024B で効果測定
- 期待: Legacy 49% → 35-40% に削減
- 結果次第で本線化 or 研究箱維持を判断
**期待効果の試算**:
- Legacy を約 15 ポイント削減
- free 全体で 5-10% 改善
- Mixed で +2-4M ops/s 程度44.8M → 47-49M ops/s
### 第二推奨: FREE-LEGACY-OPT-2 (C6-heavy Pool v1 最適化)
**優先順位**: 中
**推奨理由**:
- C6-heavy で pool_v1 が実質 100%
- 単一経路への集中最適化が可能
- 実装コストが低く、効果が確実
**実装計画**:
- pool_v1 free 経路の ENV チェック削減
- 分岐削減
- Descriptor cache hit rate 向上
**期待効果**:
- C6-heavy: 27M → 28-30M ops/s (5-10% 向上)
## Phase FREE-LEGACY-OPT-4-1 Legacy Per-Class 分析
### 目的
Legacy fallback 49.2% の内訳を per-class で分析し、どのクラスC0-C7が最も Legacy を使用しているか特定する。
### 実装内容
1. **FreePathStats 構造体の拡張** (`core/box/free_path_stats_box.h`)
- `uint64_t legacy_by_class[8]` フィールドを追加C0-C7 の Legacy fallback 内訳)
2. **デストラクタ出力の更新** (`core/box/free_path_stats_box.c`)
- `[FREE_PATH_STATS_LEGACY_BY_CLASS]` 行を追加し、C0-C7 の内訳を出力
3. **カウンタの散布** (`core/front/malloc_tiny_fast.h`)
- `free_tiny_fast()` の Legacy fallback 経路で `legacy_by_class[class_idx]` をインクリメント
- 範囲チェック0-7を実施
### 測定結果
**Run 1**:
```
[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0
```
**Run 2**:
```
[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0
```
**Run 3**:
```
[FREE_PATH_STATS] total=542031 c7_ultra=275089 small_v3=0 v6=0 tiny_v1=0 pool_v1=8081 remote=0 super_lookup=0 legacy_fb=266942
[FREE_PATH_STATS_LEGACY_BY_CLASS] c0=0 c1=0 c2=8746 c3=17279 c4=34727 c5=68871 c6=137319 c7=0
```
**測定安定性**: 完全に安定3 回とも同一の値、決定的測定)
### 平均値と比率
| クラス | サイズ範囲 | 平均呼び出し回数 | Legacy 内比率 (%) | 全体比率 (%) | 視覚化 |
|--------|-----------|---------------|-----------------|------------|--------|
| C0 | 1-16B | 0 | 0.0% | 0.0% | - |
| C1 | 17-32B | 0 | 0.0% | 0.0% | - |
| C2 | 33-64B | 8,746 | 3.3% | 1.6% | █ |
| C3 | 65-128B | 17,279 | 6.5% | 3.2% | ███ |
| C4 | 129-256B | 34,727 | 13.0% | 6.4% | ██████ |
| C5 | 257-512B | 68,871 | 25.8% | 12.7% | ████████████ |
| **C6** | **513-1024B** | **137,319** | **51.4%** | **25.3%** | **█████████████████████████** |
| C7 | 1025+B | 0 | 0.0% | 0.0% | - |
| **合計** | - | **266,942** | **100.0%** | **49.2%** | |
**注**: 全体比率 = (クラス別 Legacy / 全 free 呼び出し) × 100
### 分析
**最大シェアクラス**: **C6 (513-1024B)** が Legacy の 51.4% を占める(全体の 25.3%
**理由の推測**:
1. **サイズ分布の特性**:
- Mixed 16-1024B ベンチマークでは C6 サイズ (513-1024B) のアロケーションが多い
- C6 は Tiny の最大サイズクラスの一つで、使用頻度が高い
2. **C7 ULTRA 未対応**:
- C7 ULTRA fast path は C7 専用で、C6 はカバーしていない
- C6 は Legacy fallbackUnified Cacheに依存している
3. **v3/v4 未対応**:
- SmallHeap v3/v4 はデフォルトでは C6 をカバーしていない
- ENV `HAKMEM_SMALL_HEAP_V3_CLASSES=0x80` は C7 のみ有効化
4. **TinyHeap v1 未使用**:
- `tiny_heap_v1_fast=0` から、C6 は TinyHeap v1 経路も使用していない
- Route 設定で Legacy に直接落ちている
**次のアクション**:
Phase FREE-LEGACY-OPT-4-2 で **C6 クラス** に ULTRA-Free lane を実装する。
### 次フェーズの推奨
**対象クラス**: **C6 (513-1024B)**
**実装内容**:
1. **C6_ULTRA_FREE_BOX** の実装
- TLS に `c6_tls_freelist[32]` + `c6_tls_count` を追加
- free 時: `small_tls_owns_ptr_c6()` で range check → TLS push
- TLS full / range 外 → 既存 Legacy へフォールバック
- alloc 側は当面いじらないfree のみ前段キャッシュ)
2. **ENV ゲート**
- `HAKMEM_TINY_C6_ULTRA_FREE_ENABLED=0`(研究箱、デフォルト OFF
3. **期待される効果**
- Legacy fallback を 51% 削減C6 分)
- Legacy: 49.2% → 24-27% に改善(半減)
- 全体 throughput: +5-8% 改善
- Mixed 16-1024B: 44.8M → 47-48M ops/s 程度
4. **期待される全体への影響**
- free 経路の単純化により、C6 サイズのパフォーマンスが大幅改善
- Unified Cache への負荷軽減Legacy が半減)
- C7 ULTRA パターンの横展開による設計の一貫性向上
### 技術的洞察
**C6 が最大シェアの理由**:
1. **サイズ分布**: Mixed 16-1024B の範囲では、513-1024B が広範囲をカバー
2. **段階的展開**: C7 → C6 → C5 の順で ULTRA-Free を展開することで、段階的に Legacy を削減できる
3. **設計の妥当性**: C6 は Tiny の上限に近く、最適化の効果が大きい
**第二候補クラス**:
- **C5 (257-512B)**: Legacy の 25.8%(全体の 12.7%
- C5 も ULTRA-Free の候補だが、C6 の効果を確認してから判断すべき