Files
hakmem/docs/analysis/FREE_INC_SUMMARY.md

320 lines
8.1 KiB
Markdown
Raw Normal View History

CRITICAL FIX: TLS 未初期化による 4T SEGV を完全解消 **問題:** - Larson 4T で 100% SEGV (1T は 2.09M ops/s で完走) - System/mimalloc は 4T で 33.52M ops/s 正常動作 - SS OFF + Remote OFF でも 4T で SEGV **根本原因: (Task agent ultrathink 調査結果)** ``` CRASH: mov (%r15),%r13 R15 = 0x6261 ← ASCII "ba" (ゴミ値、未初期化TLS) ``` Worker スレッドの TLS 変数が未初期化: - `__thread void* g_tls_sll_head[TINY_NUM_CLASSES];` ← 初期化なし - pthread_create() で生成されたスレッドでゼロ初期化されない - NULL チェックが通過 (0x6261 != NULL) → dereference → SEGV **修正内容:** 全 TLS 配列に明示的初期化子 `= {0}` を追加: 1. **core/hakmem_tiny.c:** - `g_tls_sll_head[TINY_NUM_CLASSES] = {0}` - `g_tls_sll_count[TINY_NUM_CLASSES] = {0}` - `g_tls_live_ss[TINY_NUM_CLASSES] = {0}` - `g_tls_bcur[TINY_NUM_CLASSES] = {0}` - `g_tls_bend[TINY_NUM_CLASSES] = {0}` 2. **core/tiny_fastcache.c:** - `g_tiny_fast_cache[TINY_FAST_CLASS_COUNT] = {0}` - `g_tiny_fast_count[TINY_FAST_CLASS_COUNT] = {0}` - `g_tiny_fast_free_head[TINY_FAST_CLASS_COUNT] = {0}` - `g_tiny_fast_free_count[TINY_FAST_CLASS_COUNT] = {0}` 3. **core/hakmem_tiny_magazine.c:** - `g_tls_mags[TINY_NUM_CLASSES] = {0}` 4. **core/tiny_sticky.c:** - `g_tls_sticky_ss[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}` - `g_tls_sticky_idx[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}` - `g_tls_sticky_pos[TINY_NUM_CLASSES] = {0}` **効果:** ``` Before: 1T: 2.09M ✅ | 4T: SEGV 💀 After: 1T: 2.41M ✅ | 4T: 4.19M ✅ (+15% 1T, SEGV解消) ``` **テスト:** ```bash # 1 thread: 完走 ./larson_hakmem 2 8 128 1024 1 12345 1 → Throughput = 2,407,597 ops/s ✅ # 4 threads: 完走(以前は SEGV) ./larson_hakmem 2 8 128 1024 1 12345 4 → Throughput = 4,192,155 ops/s ✅ ``` **調査協力:** Task agent (ultrathink mode) による完璧な根本原因特定 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 01:27:04 +09:00
# hakmem_tiny_free.inc 構造分析 - クイックサマリー
## ファイル概要
**hakmem_tiny_free.inc** は HAKMEM メモリアロケータのメイン Free パスを実装する大規模ファイル
| 統計 | 値 |
|------|-----|
| **総行数** | 1,711 |
| **実コード行** | 1,348 (78.7%) |
| **関数数** | 10個 |
| **最大関数** | `hak_tiny_free_with_slab()` - 558行 |
| **複雑度** | CC 28 (CRITICAL) |
---
## 主要責務ベークダウン
```
hak_tiny_free_with_slab (558行, 34.2%) ← HOTTEST - CC 28
├─ SuperSlab mode handling (64行)
├─ Same-thread TLS push (72行)
└─ Magazine/SLL/Publisher paths (413行) ← 複雑でテスト困難
hak_tiny_free_superslab (305行, 18.7%) ← CRITICAL PATH - CC 16
├─ Validation & safety checks (30行)
├─ Same-thread freelist push (79行)
└─ Remote/cross-thread queue (159行)
superslab_refill (308行, 24.1%) ← OPTIMIZATION TARGET - CC 18
├─ Mid-size simple refill (36行)
├─ SuperSlab adoption (163行)
└─ Fresh allocation (70行)
hak_tiny_free (135行, 8.3%) ← ENTRY POINT - CC 12
├─ Mode selection (BENCH, ULTRA, NORMAL)
└─ Class resolution & dispatch
Other (127行, 7.7%)
├─ Helper functions (65行) - drain, remote guard
├─ SuperSlab alloc helpers (84行)
└─ Shutdown (30行)
```
---
## 関数リスト(重要度順)
### 🔴 CRITICAL (テスト困難、複雑)
1. **hak_tiny_free_with_slab()** (558行)
- 複雑度: CC 28 ← **NEEDS REFACTORING**
- 責務: Free path の main router
- 課題: Magazine/SLL/Publisher が混在
2. **superslab_refill()** (308行)
- 複雑度: CC 18
- 責務: SuperSlab adoption & allocation
- 最適化: P0 で O(n) → O(1) 化予定
3. **hak_tiny_free_superslab()** (305行)
- 複雑度: CC 16
- 責務: SuperSlab free (same/remote)
- 課題: Remote queue sentinel validation が複雑
### 🟡 HIGH (重要だが理解可能)
4. **superslab_alloc_from_slab()** (84行)
- 複雑度: CC 4
- 責務: Single slab block allocation
5. **hak_tiny_alloc_superslab()** (151行)
- 複雑度: CC ~8
- 責務: SuperSlab-based allocation entry
6. **hak_tiny_free()** (135行)
- 複雑度: CC 12
- 責務: Global free entry point (routing only)
### 🟢 LOW (シンプル)
7. **tiny_drain_to_sll_budget()** (10行) - ENV config
8. **tiny_drain_freelist_to_sll_once()** (16行) - SLL splicing
9. **tiny_remote_queue_contains_guard()** (21行) - Duplicate detection
10. **hak_tiny_shutdown()** (30行) - Cleanup
---
## 主要な複雑性源
### 1. `hak_tiny_free_with_slab()` の複雑度 (CC 28)
```c
if (!slab) {
// SuperSlab path (64行)
// ├─ SuperSlab lookup
// ├─ Validation (HAKMEM_SAFE_FREE)
// └─ if remote → hak_tiny_free_superslab()
}
// 複数の TLS キャッシュパス (72行)
// ├─ Fast path (g_fast_enable)
// ├─ TLS List (g_tls_list_enable)
// ├─ HotMag (g_hotmag_enable)
// └─ ...
// Magazine/SLL/Publisher paths (413行)
// ├─ TinyQuickSlot?
// ├─ TLS SLL?
// ├─ Magazine?
// ├─ Background spill?
// ├─ SuperRegistry spill?
// └─ Publisher fallback?
```
**課題:** Policy cascade (複数パスの判定フロー)が線形に追加されている
### 2. `superslab_refill()` の複雑度 (CC 18)
```
┌─ Mid-size simple refill (class >= 4)?
├─ SuperSlab adoption?
│ ├─ Cool-down check
│ ├─ First-fit or Best-fit scoring
│ ├─ Slab acquisition
│ └─ Binding
└─ Fresh allocation
├─ SuperSlab allocate
└─ Refcount management
```
**課題:** Adoption vs allocation decision が複雑 (Future P0 optimization target)
### 3. `hak_tiny_free_superslab()` の複雑度 (CC 16)
```
├─ Validation (bounds, magic, size_class)
├─ if (same-thread)
│ ├─ Direct freelist push
│ ├─ remote guard check
│ └─ MidTC integration
└─ else (remote)
├─ Remote queue enqueue
├─ Sentinel validation
└─ Bulk refill coordination
```
**課題:** Same vs remote path が大きく分岐
---
## 分割提案(優先度順)
### Phase 1: Magazine/SLL を分離 (413行)
**新ファイル:** `tiny_free_magazine.inc.h`
**メリット:**
- Policy cascade を独立ファイルに隔離
- Magazine は environment-based (on/off可能)
- テスト時に mock 可能
- スパイル改善時の影響を限定
```
Before: hak_tiny_free_with_slab() CC 28 → 413行
After: hak_tiny_free_with_slab() CC ~8
+ tiny_free_magazine.inc.h CC ~10
```
---
### Phase 2: SuperSlab allocation を分離 (394行)
**新ファイル:** `tiny_superslab_alloc.inc.h`
**含める関数:**
- `superslab_refill()` (308行)
- `superslab_alloc_from_slab()` (84行)
- `hak_tiny_alloc_superslab()` (151行)
- Adoption helpers
**メリット:**
- Allocation は free と直交
- P0 optimization (O(n)→O(1)) に集中
- Registry logic を明確化
---
### Phase 3: SuperSlab free を分離 (305行)
**新ファイル:** `tiny_superslab_free.inc.h`
**含める関数:**
- `hak_tiny_free_superslab()` (305行)
- Remote queue management
- Sentinel validation
**メリット:**
- Remote queue logic は pure
- Cross-thread free を focused に
- Debugging (ROUTE_MARK) が簡単
---
## 分割後の構成
### Current (1ファイル)
```
hakmem_tiny_free.inc (1,711行)
├─ Helpers & includes
├─ hak_tiny_free_with_slab (558行) ← MONOLITH
├─ SuperSlab alloc/refill (394行)
├─ SuperSlab free (305行)
├─ Main entry (135行)
└─ Shutdown (30行)
```
### After refactoring (4ファイル)
```
hakmem_tiny_free.inc (450行) ← THIN ROUTER
├─ Helpers & includes
├─ hak_tiny_free (dispatch only)
├─ hak_tiny_shutdown
└─ #include directives (3個)
tiny_free_magazine.inc.h (400行)
├─ TinyQuickSlot
├─ TLS SLL push
├─ Magazine push/spill
├─ Background spill
└─ Publisher fallback
tiny_superslab_alloc.inc.h (380行) ← P0 OPTIMIZATION HERE
├─ superslab_refill (with nonempty_mask O(n)→O(1))
├─ superslab_alloc_from_slab
└─ hak_tiny_alloc_superslab
tiny_superslab_free.inc.h (290行)
├─ hak_tiny_free_superslab
├─ Remote queue management
└─ Sentinel validation
```
---
## 実装手順
### Step 1: バックアップ
```bash
cp core/hakmem_tiny_free.inc core/hakmem_tiny_free.inc.bak
```
### Step 2-4: 3ファイルに分割
```
Lines 208-620 → core/tiny_free_magazine.inc.h
Lines 626-1019 → core/tiny_superslab_alloc.inc.h
Lines 1171-1475 → core/tiny_superslab_free.inc.h
```
### Step 5: Makefile update
```makefile
hakmem_tiny_free.inc は #include で 3ファイルを参照
→ dependency に追加
```
### Step 6: 検証
```bash
make clean && make
./larson_hakmem 2 8 128 1024 1 12345 4
# スコア変化なし を確認
```
---
## 分割前後の改善指標
| 指標 | Before | After | 改善 |
|------|--------|-------|------|
| **ファイル数** | 1 | 4 | +300% (関心分離) |
| **avg CC** | 14.4 | 8.2 | **-43%** |
| **max CC** | 28 | 16 | **-43%** |
| **max func size** | 558行 | 308行 | **-45%** |
| **理解難易度** | ★★★★☆ | ★★★☆☆ | **-1段階** |
| **テスト容易性** | ★★☆☆☆ | ★★★★☆ | **+2段階** |
---
## 関連最適化
### P0 Optimization (Already in CLAUDE.md)
- **File:** `tiny_superslab_alloc.inc.h` (after split)
- **Location:** `superslab_refill()` lines ~785-947
- **Optimization:** O(n) linear scan → O(1) ctz using `nonempty_mask`
- **Expected:** CPU 29.47% → 25.89% (-12%)
### P1 Opportunities (After split)
1. Magazine policy tuning (dedicated file で容易)
2. SLL fast path 最適化 (isolation で実験容易)
3. Publisher fallback 削減 (cache hit rate 改善)
---
## ドキュメント参照
- **Full Analysis:** `/mnt/workdisk/public_share/hakmem/STRUCTURAL_ANALYSIS.md`
- **Related:** `CLAUDE.md` (Phase 6-2.1 P0 optimization)
- **History:** `HISTORY.md` (Past refactoring lessons)
---
## 実施推奨度
**★★★★★ STRONGLY RECOMMENDED**
理由:
1. hak_tiny_free_with_slab の CC 28 は危険域
2. Magazine/SLL paths は独立policy (隔離が自然)
3. P0 optimization が superslab_refill に focused
4. テスト時の mock 可能性が大幅向上
5. Future maintenance が容易に