Files
hakmem/HAKMEM_ARCHITECTURE_OVERVIEW.md
Moe Charm (CI) 0546454168 WIP: Add TLS SLL validation and SuperSlab registry fallback
ChatGPT's diagnostic changes to address TLS_SLL_HDR_RESET issue.
Current status: Partial mitigation, but root cause remains.

Changes Applied:
1. SuperSlab Registry Fallback (hakmem_super_registry.h)
   - Added legacy table probe when hash map lookup misses
   - Prevents NULL returns for valid SuperSlabs during initialization
   - Status:  Works but may hide underlying registration issues

2. TLS SLL Push Validation (tls_sll_box.h)
   - Reject push if SuperSlab lookup returns NULL
   - Reject push if class_idx mismatch detected
   - Added [TLS_SLL_PUSH_NO_SS] diagnostic message
   - Status:  Prevents list corruption (defensive)

3. SuperSlab Allocation Class Fix (superslab_allocate.c)
   - Pass actual class_idx to sp_internal_allocate_superslab
   - Prevents dummy class=8 causing OOB access
   - Status:  Root cause fix for allocation path

4. Debug Output Additions
   - First 256 push/pop operations traced
   - First 4 mismatches logged with details
   - SuperSlab registration state logged
   - Status:  Diagnostic tool (not a fix)

5. TLS Hint Box Removed
   - Deleted ss_tls_hint_box.{c,h} (Phase 1 optimization)
   - Simplified to focus on stability first
   - Status:  Can be re-added after root cause fixed

Current Problem (REMAINS UNSOLVED):
- [TLS_SLL_HDR_RESET] still occurs after ~60 seconds of sh8bench
- Pointer is 16 bytes offset from expected (class 1 → class 2 boundary)
- hak_super_lookup returns NULL for that pointer
- Suggests: Use-After-Free, Double-Free, or pointer arithmetic error

Root Cause Analysis:
- Pattern: Pointer offset by +16 (one class 1 stride)
- Timing: Cumulative problem (appears after 60s, not immediately)
- Location: Header corruption detected during TLS SLL pop

Remaining Issues:
⚠️ Registry fallback is defensive (may hide registration bugs)
⚠️ Push validation prevents symptoms but not root cause
⚠️ 16-byte pointer offset source unidentified

Next Steps for Investigation:
1. Full pointer arithmetic audit (Magazine ⇔ TLS SLL paths)
2. Enhanced logging at HDR_RESET point:
   - Expected vs actual pointer value
   - Pointer provenance (where it came from)
   - Allocation trace for that block
3. Verify Headerless flag is OFF throughout build
4. Check for double-offset application in conversions

Technical Assessment:
- 60% root cause fixes (allocation class, validation)
- 40% defensive mitigation (registry fallback, push rejection)

Performance Impact:
- Registry fallback: +10-30 cycles on cold path (negligible)
- Push validation: +5-10 cycles per push (acceptable)
- Overall: < 2% performance impact estimated

Related Issues:
- Phase 1 TLS Hint Box removed temporarily
- Phase 2 Headerless blocked until stability achieved

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 20:42:28 +09:00

36 KiB
Raw Blame History

HAKMEM アーキテクチャ全体像 - 設計質問状

作成日: 2025-11-28 目的: ChatGPT に設計相談するための全体像整理


Part 1: HAKMEM の全体アーキテクチャ

1.1 4層構造の概要

HAKMEMは4層アーキテクチャで設計されています:

┌─────────────────────────────────────────────────────────────────┐
│ Layer 0 (L0): Tiny Pool - ≤1KB アロケータ                      │
│   - 8つのサイズクラス (8B, 16B, 32B, 64B, 128B, 256B, 512B, 1KB)│
│   - TLS Magazine (高速キャッシュ)                               │
│   - TLS SLL (Single-Linked List: 無制限オーバーフロー)          │
│   - TLS Active Slab (Arena-lite: 所有スレッドがロックレス割当) │
│   - SuperSlab バックエンド (64KB slab × 複数)                  │
│   - MPSC remote-free queue (クロススレッド free)                │
│   - 実装: core/hakmem_tiny.{c,h}                                │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 1 (L1): ACE Layer - 1KB2MB アロケータ + 学習エンジン   │
│                                                                  │
│   [Mid Pool] 2KB32KB (5クラス: 2/4/8/16/32KB)                │
│     - TLS キャッシュ + Shared Pool                             │
│     - W_MAX rounding (切り上げ許容: 32KB→64KB等)               │
│     - DYN1/DYN2: 可変サイズクラス (学習で最適化)                │
│                                                                  │
│   [Large Pool] 64KB1MB (5クラス: 64/128/256/512KB/1MB)       │
│     - Bundle-based refill (バンドル単位でリフィル)              │
│     - CAP学習 (ヒット率ベースで容量自動調整)                    │
│                                                                  │
│   [ACE Controller] 学習エンジン                                 │
│     - ACE = Agentic Context Engineering                         │
│       (実装コンテキストでは Adaptive Control/Cache Engine   │
│     - CAP学習: ヒット率 vs 目標値 → CAP ±Δ                     │
│     - W_MAX学習: UCB1 bandit + Canary deployment               │
│     - DYN1自動割り当て: サイズヒストグラムからピーク検出         │
│     - Budget制約: 合計CAP上限管理 + Water-filling配分          │
│     - 実装: core/hakmem_learner.{c,h}, hakmem_ace_controller.{c,h}│
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 2 (L2): Big Cache - ≥2MB アロケータ                      │
│   - BigCache: サイズクラスキャッシュ (Tier-2最適化)             │
│   - mmap/munmap (THP: Transparent Huge Pages 対応)             │
│   - Batch madvise: MADV_DONTNEED バッチ化 (syscall削減)        │
│   - THP threshold学習: UCB1/Canary方式で最適閾値を自動決定      │
│   - 実装: core/hakmem_bigcache.{c,h}, hakmem_batch.{c,h}       │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│ Layer 3: Policy & Learning Infrastructure                       │
│   - FrozenPolicy: RCUライクなポリシースナップショット           │
│   - Site Rules: コールサイト別ルーティングヒント (オプション)   │
│   - P² percentile: O(1)メモリでp99推定                          │
│   - ELO rating: 戦略評価 + Softmax選択                         │
│   - 実装: core/hakmem_policy.{c,h}, hakmem_elo.{c,h}           │
└─────────────────────────────────────────────────────────────────┘

1.2 各層の責任と相互作用

Layer 0: Tiny Pool (≤1KB)

責任:

  • 小サイズアロケーション (8B1KB) の超高速処理
  • TLS (Thread-Local Storage) による競合回避
  • クロススレッド free の安全処理 (MPSC queue)

主要データ構造:

  • TinyTLSSLL: 単方向連結リスト (head, count)
  • TinySlab: 64KB slab, bitmap管理
  • SuperSlab: 複数slabの親構造 (Phase 7で導入)
  • g_tls_sll[8]: クラスごとのTLS SLL (スレッドローカル)

データフロー (Alloc):

1. TLS SLL pop (3-4命令, 5-10サイクル) → HIT (85-90%)
   ├─ hit → ユーザーポインタ返却 (base+1)
   └─ miss → 2へ

2. TLS Active Slab (bitmap scan, 5-6ns) → HIT (8-12%)
   ├─ hit → ブロック確保 → TLS SLLにpush → 1へ戻る
   └─ miss → 3へ

3. SuperSlab refill (バッチ補充, 32-128ブロック) → HIT (1-3%)
   ├─ success → TLS SLLにバッチpush → 1へ戻る
   └─ fail → mmapで新SuperSlab確保

データフロー (Free):

1. Header読み取り (2-3サイクル) → class_idx決定
   ├─ 1-byte header: 0xA0 | class_idx
   └─ C0,C7: offset 0 / C1-6: offset 1

2. TLS SLL push (3-4命令) → 完了 (95-99%)
   ├─ Same thread → TLS SLLに直接push
   └─ Cross thread → MPSC remote queueに追加

3. Periodic drain (2048 frees毎) → Freelist還元
   ├─ TLS SLL → Slab freelist へ移動
   └─ meta->used-- (使用中ブロック数デクリメント)

関連ファイル:

  • /mnt/workdisk/public_share/hakmem/core/hakmem_tiny.{c,h} (2228行)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_tiny_superslab.{c,h} (SuperSlab管理)
  • /mnt/workdisk/public_share/hakmem/core/box/tls_sll_box.h (TLS SLL API, 753行)
  • /mnt/workdisk/public_share/hakmem/core/tiny_region_id.h (Header操作, 222行)

Layer 1: ACE Layer (1KB2MB) + Learning

責任:

  • 中~大サイズアロケーション (1KB2MB) の効率的処理
  • ヒット率ベース学習による容量自動調整
  • W_MAX rounding (柔軟なサイズクラス選択)

主要データ構造:

  • FrozenPolicy: スナップショット (mid_cap[5], large_cap[5], w_max_mid, w_max_large)
  • PoolStats: ヒット/ミスカウンタ (窓ごとに集計)
  • ucb1_t: UCB1 bandit構造 (候補値, pulls, sum_score)

学習アルゴリズム:

【CAP学習】(実装済)
  窓長: 1秒 (HAKMEM_LEARN_WINDOW_MS=1000)

  For each class c in {Mid0..4, Large0..4}:
    hit_rate_c = Δhits_c / (Δhits_c + Δmisses_c)

    IF hit_rate_c < target_c - eps:
      cap_c += step_c  (不足 → 増加)
    ELIF hit_rate_c > target_c + eps:
      cap_c -= step_c  (過剰 → 減少)

    cap_c = clamp(cap_c, min_c, max_c)

  Budget制約:
    IF sum(cap_mid) > BUDGET_MID:
      → 需要低いクラスから削減
    ELIF sum(cap_mid) < BUDGET_MID && WATER_FILLING:
      → 需要高いクラスへ配分

【W_MAX学習】(実装済)
  UCB1 bandit:
    候補: [1.4, 1.6, 1.8, 2.0]  (Mid)
           [1.25, 1.5, 1.75, 2.0] (Large)

    For each arm i:
      UCB_i = mean_score_i + 1.5 * sqrt(log(total_pulls) / pulls_i)

    Select: arm = argmax(UCB_i)

  Canary deployment:
    試行期間: dwell_sec (35秒)
    評価: ヒット率改善度
    改善なし → ロールバック

【DYN1学習】(実装済)
  サイズヒストグラム:
    ピーク検出 → 固定クラスと被らない範囲で動的クラス設定
    例: 8-16KB ギャップを 12KB で埋める

データフロー (Alloc):

1. FrozenPolicy読み込み (1回, 関数冒頭)
   pol = hkm_policy_get()

2. W_MAX判定
   IF class ≤ W_MAX × size:
     class = round_up(size, class_stride)

3. Pool TLS キャッシュ → HIT (65-85%)
   ├─ hit → 返却
   └─ miss → 4へ

4. Shared Pool refill → HIT (10-20%)
   ├─ success → TLS補充 → 3へ戻る
   └─ fail → malloc fallback (1-5%)

環境変数:

# 学習有効化
HAKMEM_LEARN=1

# 目標ヒット率
HAKMEM_TARGET_HIT_MID=0.65    # Mid: 65%
HAKMEM_TARGET_HIT_LARGE=0.55  # Large: 55%

# CAP調整ステップ
HAKMEM_CAP_STEP_MID=4         # Mid: 4 pages/update
HAKMEM_CAP_STEP_LARGE=1       # Large: 1 bundle/update

# Budget制約
HAKMEM_BUDGET_MID=300         # Mid総CAP上限: 300 pages
HAKMEM_BUDGET_LARGE=50        # Large総CAP上限: 50 bundles

# W_MAX学習
HAKMEM_WMAX_LEARN=1
HAKMEM_WMAX_CANDIDATES_MID=1.4,1.6,1.8
HAKMEM_WMAX_CANDIDATES_LARGE=1.25,1.5,2.0

# DYN1自動割り当て
HAKMEM_DYN1_AUTO=1
HAKMEM_MID_DYN1=12288         # 12KB

関連ファイル:

  • /mnt/workdisk/public_share/hakmem/core/hakmem_ace.{c,h} (L1統合)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_learner.{c,h} (学習エンジン, 900行)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_pool.{c,h} (Mid Pool)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_l25_pool.{c,h} (Large Pool)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_ace_controller.{c,h} (ACE制御)

Layer 2: Big Cache (≥2MB)

責任:

  • 大サイズアロケーション (≥2MB) のキャッシュ
  • mmap/munmap syscall削減
  • THP (Transparent Huge Pages) 活用

主要データ構造:

  • BigCache: サイズクラス別キャッシュ (hash map)
  • BatchMadvise: MADV_DONTNEED バッチ構造

データフロー:

1. BigCache lookup → HIT (20-40%)
   ├─ hit → 返却
   └─ miss → 2へ

2. mmap (MAP_ANONYMOUS | MAP_PRIVATE)
   ├─ size ≥ thp_threshold → MADV_HUGEPAGE hint
   └─ success → キャッシュに登録

Free:
  1. BigCache push (容量制限あり)
     ├─ 空きあり → キャッシュ保持
     └─ 満杯 → 3へ

  2. BatchMadvise追加
     ├─ batch_size < limit → バッチに追加
     └─ batch_size ≥ limit → 3へ

  3. Batch flush: MADV_DONTNEED一括呼び出し

関連ファイル:

  • /mnt/workdisk/public_share/hakmem/core/hakmem_bigcache.{c,h} (210行)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_batch.{c,h} (120行)

Layer 3: Policy & Learning Infrastructure

責任:

  • ポリシー管理 (RCU-like snapshot)
  • 学習基盤 (統計, 評価, 選択)

主要データ構造:

  • FrozenPolicy: 読み取り専用スナップショット
  • p2_t: P²アルゴリズム状態 (O(1) p99推定)
  • elo_t: ELO rating構造

FrozenPolicy RCU-like更新:

Writer (learner thread):
  1. 新ポリシー作成
     new_pol = malloc(sizeof(FrozenPolicy))
     new_pol->mid_cap[0] = 128
     new_pol->generation++

  2. Atomic publish
     hkm_policy_publish(new_pol)

Reader (hot path):
  1. Snapshot取得 (1回, 関数冒頭)
     const FrozenPolicy* pol = hkm_policy_get()

  2. 読み取り専用参照
     cap = pol->mid_cap[class_idx]

Grace period: なし (単純な世代管理, 旧ポリシーは上書き)

関連ファイル:

  • /mnt/workdisk/public_share/hakmem/core/hakmem_policy.{c,h} (50行)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_p2.{c,h} (P²アルゴリズム, 130行)
  • /mnt/workdisk/public_share/hakmem/core/hakmem_elo.{c,h} (ELO rating, 450行)

1.3 データフロー全体像

malloc(size) 呼び出し
    |
    v
[サイズ判定]
    |
    +---> size ≤ 1KB ---------> Layer 0 (Tiny Pool)
    |                              |
    |                              v
    |                          TLS SLL pop (5-10ns)
    |                              |
    |                              v
    |                          ユーザーポインタ返却
    |
    +---> 1KB < size < 2MB ---> Layer 1 (ACE)
    |                              |
    |                              v
    |                          FrozenPolicy取得
    |                              |
    |                              v
    |                          W_MAX判定 → class選択
    |                              |
    |                              v
    |                          Pool TLS キャッシュ
    |                              |
    |                              v
    |                          ユーザーポインタ返却
    |
    +---> size ≥ 2MB ----------> Layer 2 (Big Cache)
                                   |
                                   v
                               BigCache lookup
                                   |
                                   v
                               mmap (miss時)
                                   |
                                   v
                               ユーザーポインタ返却

free(ptr) 呼び出し
    |
    v
[Header読み取り]
    |
    v
class_idx = *(uint8_t*)ptr - 1 & 0x07
    |
    +---> class_idx < 8 -------> Layer 0 (Tiny Pool)
    |                              |
    |                              v
    |                          TLS SLL push (3-4命令)
    |                              |
    |                              v
    |                          完了 (95-99%)
    |
    +---> class_idx ≥ 8 -------> classify_ptr() (slow path)
                                   |
                                   v
                               Registry lookup (50-100サイクル)
                                   |
                                   v
                               Layer 1 or Layer 2 へルーティング

Part 2: TLS SLL の位置づけと問題点

2.1 TLS SLL の本来の目的

設計意図:

  • Thread-Local Storage による競合回避
  • Lock-free な高速 free パス (3-4命令, 5-10サイクル)
  • 無制限オーバーフロー (Magazine容量制限なし)

Box Theory 位置づけ:

  • Layer 2 (Fast Path): Alloc/Free の最速経路
  • Box 5 (TLS-SLL First): SLL優先、miss時にHotMag/TLS list fallback

他層との相互作用:

TLS SLL ←→ TLS Active Slab
  - refill: Slab bitmap scan → TLS SLLにバッチpush
  - drain: TLS SLL → Slab freelist (periodic, 2048 frees毎)

TLS SLL ←→ SuperSlab
  - carve: SuperSlab線形切り出し → TLS SLLに供給
  - free: MPSC remote queue → SuperSlab freelist (cross-thread)

TLS SLL ←→ ACE Learning
  - capacity決定: sll_cap_for_class(class_idx) → 学習で最適容量
  - metrics: TLS SLL hit/miss → 学習入力

2.2 Header/Next 競合問題の詳細

問題の本質

物理制約:

  • Class 0 (8B): [1B header][7B payload] → 8Bポインタ入らない
  • Class 1-6 (16B512B): [1B header][payload ≥ 8B] → 可能だが user data と干渉
  • Class 7 (2048B): [1B header][2047B payload] → 可能

設計ルール (tiny_nextptr.h):

// Phase E1-CORRECT FINAL
static inline size_t tiny_next_off(int class_idx) {
#if HAKMEM_TINY_HEADER_CLASSIDX
    // Class 0, 7 → offset 0 (freelist中はheader潰す)
    //   - C0: 物理制約 (8Bポインタ入らない)
    //   - C7: 設計選択 (next をuser dataから隔離)
    // Class 1-6 → offset 1 (header保持)
    return (class_idx == 0 || class_idx == 7) ? 0u : 1u;
#else
    return 0u;
#endif
}

競合のメカニズム:

[Alloc時]
  1. base から user pointer 作成
     user = base + 1  (C1-6)
     user = base      (C0, C7)

  2. Header書き込み
     *(uint8_t*)base = 0xA0 | class_idx

  3. ユーザーに返却

[Free時]
  1. Header読み取り
     class_idx = *(uint8_t*)(ptr-1) & 0x07

  2. Next pointer書き込み (freelist構築)
     ※ Class 0, 7: base+0 に書き込み → Header上書き
     ※ Class 1-6: base+1 に書き込み → Header保持

  3. TLS SLL push
     g_tls_sll[class_idx].head = base

問題の顕在化:

  • Phase 7: 直接TLS push (3命令) → 59-70M ops/s
  • commit b09ba4d40: Box TLS-SLL導入 (150行) → 6-9M ops/s (-85-93%!)
    • 理由: Header/Next競合回避のため、複雑な正規化・チェック追加
    • コスト: 10-20倍のオーバーヘッド

2.3 現在の問題点

問題1: TLS SLL と meta->used の同期不整合

現象:

  • TLS SLL push/pop 時、meta->used (使用中ブロック数) が更新されない
  • Periodic drain (2048 frees毎) まで meta->used は高いまま
  • Slab が "full" に見える → 再利用されない → メモリリーク
  • Slab 再利用時、TLS SLL に古いポインタ残存 → double-free

根本原因:

// tiny_free_fast_v2.inc.h (fast path, 95-99%)
void* base = (char*)ptr - 1;
tls_sll_push(class_idx, base, UINT32_MAX);  // meta->used は変更なし!

// free_local_box.c (slow path, 1-5% or periodic drain)
meta->used--;  // ← 唯一の decrement 箇所

影響:

  • Larson ベンチマーク: double-free クラッシュ (30%)
  • 長時間稼働: メモリリーク + 性能劣化

問題2: Box TLS-SLL の過剰オーバーヘッド

Phase 7 (直接push):

// 3命令, 5-10サイクル
*(void**)base = g_tls_sll_head[class_idx];  // 1 mov
g_tls_sll_head[class_idx] = base;            // 1 mov
g_tls_sll_count[class_idx]++;                // 1 inc

Current (Box TLS-SLL):

// 150行, 50-100サイクル (release), 100-1000サイクル (debug)
if (!tls_sll_push(class_idx, base, UINT32_MAX)) {
    // 内部処理:
    // - Bounds check (重複)
    // - Capacity check (重複)
    // - User pointer check (35行, debug)
    // - Header restoration (5行)
    // - Double-free scan (O(n), 100-1000サイクル, debug)
    // - PTR_TRACK macros
    // - やっと push (3命令)
}

性能影響:

  • Phase 7: 59-70M ops/s
  • Current: 6-9M ops/s (-85-93%)
  • Box TLS-SLL導入 (commit b09ba4d40) が主原因

問題3: 設計上の矛盾

矛盾点:

  • Free パスが Header を読む必要がある (class_idx決定)
  • 「Header は Alloc で書く」設計との矛盾
    • Alloc: Header書き込み
    • Free: Header読み取り → class_idx取得
    • Freelist構築: Next pointer書き込み → Header上書き (C0, C7)
    • Next Alloc: Header読めない! → Registry lookup fallback (50-100サイクル)

Phase E3-1 の失敗:

  • 意図: Registry lookup削除 → +226-443%改善
  • 実際: Registry lookup は slow path (1-5%) にあり、fast path (95-99%) にはない
  • 結果: 無関係な overhead 追加 → -10-38%劣化

Part 3: ChatGPT 用質問状

3.1 アーキテクチャ全般

Q1: 4層設計の妥当性

背景:

  • Layer 0 (Tiny): TLS主体, ≤1KB
  • Layer 1 (ACE): Pool主体, 1KB2MB, 学習機能
  • Layer 2 (Big): mmap主体, ≥2MB
  • Layer 3 (Policy): 学習基盤, ポリシー管理

質問:

  1. この4層分離は適切か 統合すべき層はあるか?
  2. 各層の責任境界は明確か? オーバーラップはないか?
  3. 学習層 (Layer 3) を独立させるメリット/デメリットは?

期待する回答:

  • 層分離の設計原則 (SoC, SRP等)
  • 類似アロケータ (jemalloc, mimalloc, tcmalloc) との比較
  • 学習層の位置づけ (横断的関心事 vs 垂直統合)

Q2: 層間インターフェース設計

背景:

  • Layer 0 ↔ Layer 1: malloc(1024) は Layer 0 か Layer 1 か?
  • FrozenPolicy: Layer 3 が生成、Layer 0/1/2 が参照
  • 学習メトリクス: Layer 0/1/2 が収集、Layer 3 が消費

質問:

  1. 境界サイズ (1KB) の扱いは適切か? オーバーラップ許容すべきか?
  2. FrozenPolicy の RCU-like更新は妥当か Grace period不要で問題ないか
  3. メトリクス収集のインターフェースは適切か? (push vs pull)

期待する回答:

  • Boundary alignment の設計パターン
  • RCU の正しい実装方法 (grace period, quiescent state)
  • Metrics pipeline の設計 (sampling, aggregation, backpressure)

3.2 TLS SLL の設計

Q3: Header/Next 競合問題の回避策

背景:

  • Class 0 (8B): 物理的に next pointer 入らない
  • Class 7 (2048B): User data 保護のため offset 0 選択
  • Class 1-6 (16B512B): Header保持可能だが、freelist時に next pointer と干渉

現在の解決策:

  • Phase E1-CORRECT: C0/C7は offset 0 (header潰す), C1-6は offset 1 (header保持)
  • Box TLS-SLL: 複雑な正規化・チェック (150行, 50-100サイクル)

質問:

  1. 別の設計案: Header を別領域 (slab metadata) に保存?
  2. Trade-off: Memory overhead (1B/block) vs CPU overhead (50-100サイクル)?
  3. 他アロケータの解決策: jemalloc, mimalloc, tcmalloc はどう解決?

期待する回答:

  • Header配置の設計パターン (in-band vs out-of-band)
  • Metadata storage strategies (embed vs separate)
  • Performance vs safety の適切なバランス

Q4: TLS SLL と meta->used の同期設計

背景:

  • Fast path (95-99%): TLS SLL push/pop のみ → meta->used 更新なし
  • Slow path (1-5%): tiny_free_local_box()meta->used--
  • Periodic drain (2048 frees毎): TLS SLL → freelist → meta->used--

問題:

  • Slab empty判定 (meta->used == 0) が遅延
  • TLS SLL に古いポインタ残存 → double-free

質問:

  1. 同期戦略:
    • Option A: Fast path でも meta->used 更新 (atomicコスト)
    • Option B: TLS SLL count を meta->used に含める (複雑化)
    • Option C: Periodic drain 頻度を上げる (CPU overhead)
  2. 他アロケータ: tcache (glibc), mimalloc の TLS キャッシュはどう同期?
  3. Best practice: Lock-free TLS cache と shared metadata の同期パターン

期待する回答:

  • Consistency model の選択 (eventual vs strong)
  • Performance vs correctness の trade-off
  • Proven solutions (既知の良い解決策)

Q5: Thread-Local Storage の活用方法

背景:

  • TLS SLL: 無制限容量、ロックフリー
  • TLS Active Slab: 所有スレッドのみ割当、ロックレス
  • MPSC remote queue: クロススレッド free

質問:

  1. TLS設計の妥当性:
    • SLL + Active Slab の二重キャッシュは冗長? 統合すべき?
    • Magazine (固定容量) vs SLL (無制限) のメリット/デメリット
  2. Remote free戦略:
    • MPSC queue は適切? SPSC (per-thread) の方が良い?
    • Drain タイミング: periodic vs threshold vs on-demand
  3. 他アロケータとの比較:
    • jemalloc: thread cache
    • mimalloc: thread-local heap
    • tcmalloc: per-thread cache

期待する回答:

  • TLS cache の設計原則 (size, structure, eviction)
  • Remote free の best practice (queue type, drain strategy)
  • Multi-tier cache の適切な構成

3.3 学習層の設計

Q6: 学習アルゴリズムの選択

背景:

  • CAP学習: ヒット率ベース PID制御
  • W_MAX学習: UCB1 bandit + Canary deployment
  • DYN1学習: サイズヒストグラム + ピーク検出

質問:

  1. PID制御の妥当性:
    • 現在: P制御のみ (比例項)
    • 追加すべき: I制御 (積分項), D制御 (微分項)?
    • Over-/Under-shoot リスクは?
  2. UCB1の選択理由:
    • Thompson Sampling, Epsilon-greedy との比較
    • Exploration/Exploitation バランスの調整方法
  3. オンライン学習のリスク:
    • 誤学習 (noise, workload shift)
    • 振動 (oscillation)
    • 収束失敗 (divergence)

期待する回答:

  • Adaptive control の設計パターン (PID, MPC, RL)
  • Bandit algorithm の選択基準
  • Online learning の安全対策 (bounds, damping, rollback)

Q7: オンライン学習 vs オフライン学習

背景:

  • 現在: オンライン学習 (実行中に継続的に調整)
  • 代替案: オフライン学習 (プロファイル → 最適化 → 固定)

質問:

  1. オンライン学習のメリット/デメリット:
    • Pro: Workload変化に適応
    • Con: CPU overhead, 誤学習リスク
  2. Hybrid approach:
    • LEARN → FROZEN → CANARY (現在実装済)
    • 改善点: 収束判定, 再学習トリガー
  3. Production deployment:
    • 学習モードはいつ使う? (開発 vs 本番)
    • Profile-Guided Optimization (PGO) との統合

期待する回答:

  • Adaptive system の適用範囲 (when to use online learning)
  • Convergence detection の手法
  • PGO との統合パターン

Q8: 学習結果の活用方法

背景:

  • FrozenPolicy: 学習結果を RCU-like に publish
  • Hot path: hkm_policy_get() で snapshot取得、読み取り専用参照

質問:

  1. RCU-like更新の妥当性:
    • Grace period なし → 問題ないか?
    • Stale read のリスク (古いポリシー参照)
  2. Policy versioning:
    • generation カウンタで十分?
    • ABA problem のリスクは?
  3. Hot path overhead:
    • hkm_policy_get() のコスト (キャッシュヒット前提)
    • Inlining 戦略

期待する回答:

  • RCU の正しい実装 (grace period, quiescent state, memory barriers)
  • Versioning scheme の設計
  • Hot path optimization techniques

3.4 メモリ構造

Q9: Header の設計

背景:

  • 1-byte header: 0xA0 | class_idx
  • 位置: block base (user pointer - 1)
  • 内容: magic (0xA0) + class index (0-7)

質問:

  1. Header size の妥当性:
    • 1B → 0.1% overhead (1KB block)
    • 2B → more info (flags, ownership, etc.)?
  2. Magic number の必要性:
    • 0xA0 で corruption detection 十分?
    • CRC/Checksum は過剰?
  3. In-band vs Out-of-band:
    • 現在: In-band (user data に embedding)
    • 代替案: Out-of-band (slab metadata に保存)

期待する回答:

  • Header design patterns (size, content, placement)
  • Corruption detection strategies
  • Trade-off analysis (memory vs CPU)

Q10: Next ポインタとの共存問題

背景:

  • Next pointer: freelist 構築用 (8B)
  • Header: allocation metadata (1B)
  • 競合: Class 0/7 は offset 0 (header 上書き)

質問:

  1. 共存戦略の評価:
    • 現在: C0/C7 は offset 0, C1-6 は offset 1
    • 代替案A: 全クラス offset 0 (header は別領域)
    • 代替案B: 全クラス offset 1 (C0 は 16B に promote)
  2. 他アロケータの解決策:
    • jemalloc: chunk header (別領域)
    • mimalloc: page header (別領域)
    • tcmalloc: span metadata (別領域)
  3. Performance impact:
    • Header read/write のコスト
    • Cache line 効率

期待する回答:

  • Metadata placement の best practice
  • Performance vs simplicity の評価
  • Industry standard solutions

Q11: Size class の設計

背景:

  • Tiny (L0): 8クラス (8, 16, 32, 64, 128, 256, 512, 2048B)
  • Mid (L1): 5クラス (2, 4, 8, 16, 32KB) + DYN1/DYN2
  • Large (L1): 5クラス (64, 128, 256, 512KB, 1MB)

質問:

  1. Class granularity の妥当性:
    • Tiny: power-of-2 → 内部断片化 (最大50%)
    • Mid/Large: fewer classes → 切り上げ許容 (W_MAX)
  2. Dynamic size class (DYN1/DYN2):
    • ピーク検出でギャップ埋める
    • リスク: 過学習 (overfitting), クラス爆発
  3. 他アロケータとの比較:
    • jemalloc: 40+ classes (細粒度)
    • mimalloc: 74 classes (超細粒度)
    • tcmalloc: ~60 classes

期待する回答:

  • Size class design の原則 (granularity, coverage, fragmentation)
  • Dynamic sizing の適用範囲
  • Industry standard configurations

3.5 並行性

Q12: Lock-free 設計のトレードオフ

背景:

  • TLS SLL: Lock-free (thread-local only)
  • MPSC remote queue: Lock-free (atomic CAS)
  • Slab freelist: Mutex-protected (per-class lock)

質問:

  1. Lock-free の適用範囲:
    • 現在: TLS hot path のみ
    • 拡張可能: Shared pool refill も lock-free化
  2. ABA problem 対策:
    • MPSC queue: ポインタのみ (no counter)
    • リスク: ABA発生時の影響
  3. Performance vs Complexity:
    • Lock-free は本当に速い? (cache ping-pong リスク)
    • Mutex (futex) で十分な場合は?

期待する回答:

  • Lock-free design の適用基準
  • ABA problem の解決策 (tagged pointer, epoch-based GC)
  • When to use lock-free vs lock-based

Q13: スレッド間のデータ共有

背景:

  • FrozenPolicy: 全スレッド読み取り (writer 1, reader N)
  • SuperSlab registry: 全スレッド参照 (lookup用)
  • MPSC remote queue: cross-thread free

質問:

  1. Read-heavy shared data の最適化:
    • FrozenPolicy: RCU適切 Seq-lock の方が良い?
    • Registry: Lock-free hash table vs Mutex-protected
  2. Write contention の回避:
    • Learner thread: 書き込み頻度 (1秒毎) は適切?
    • Batch update で contention 削減可能?
  3. Cache coherence overhead:
    • False sharing リスク (padding戦略)
    • NUMA awareness (今後の課題)

期待する回答:

  • Read-heavy workload の最適化手法
  • Write contention の設計パターン
  • Cache coherence の考慮事項

Q14: Race condition の回避パターン

背景:

  • meta->used vs TLS SLL count の不整合
  • Slab reuse 時の TLS SLL クリア漏れ
  • Double-free 検出 (debug mode)

質問:

  1. Current bugs の根本原因:
    • meta->used 同期問題は設計欠陥? 実装バグ?
    • 正しい同期モデルは? (eventual consistency vs strong consistency)
  2. Double-free prevention:
    • TLS SLL duplicate scan (debug) は十分?
    • Release mode でも detection 必要? (Sanitizer dependency)
  3. Testing strategy:
    • Race condition の再現方法
    • ThreadSanitizer (TSan) の限界

期待する回答:

  • Concurrency bugs の分類 (data race, deadlock, ABA, etc.)
  • Prevention strategies (design patterns, tools)
  • Testing methodology (stress test, model checking, formal verification)

Part 4: 現状の問題点整理

4.1 Header/Next 競合問題

問題の詳細:

  1. 設計矛盾:

    • Free path: Header読み取り必要 (class_idx決定)
    • Freelist構築: Next pointer書き込み → Header上書き (C0, C7)
    • Next alloc: Header読めない → Registry lookup (50-100サイクル)
  2. これまでの修正試行:

    • Phase E1-CORRECT: C0/C7は offset 0, C1-6は offset 1
    • Box TLS-SLL: 複雑な正規化 (150行, 50-100サイクル)
    • Phase E3-1: Registry lookup削除試行 → 失敗 (-10-38%)
  3. 根本原因:

    • 物理制約 (C0: 8B block に 8B pointer 入らない)
    • 設計選択 (C7: user data 保護 vs header保持)
    • Trade-off未解決 (memory overhead vs CPU overhead)

4.2 TLS SLL と meta->used の同期問題

問題の詳細:

  1. Fast path (95-99%): TLS SLL push/pop のみ → meta->used 更新なし
  2. Slow path (1-5% or drain): tiny_free_local_box() → meta->used--
  3. Slab empty判定の遅延: meta->used 高いまま → 再利用されない → リーク
  4. TLS SLL クリア漏れ: Slab reuse 時、古いポインタ残存 → double-free

修正試行:

  • Periodic drain 間隔調整 (2048 → 512 frees)
  • Adaptive drain (hot classes 頻度↑)
  • TLS SLL clear on slab reuse (debug mode)

根本原因:

  • 設計レベルの問題: Fast path と meta->used が分離
  • 同期モデル未定義: Eventual consistency? Strong consistency?

4.3 本番ビルドでも30%クラッシュ

現象:

  • Larson benchmark: 30% crash rate (double-free)
  • Release build でも発生 → 診断コードではなく実際のバグ
  • Multi-thread 環境で再現性高い

原因:

  1. TLS SLL と meta->used の同期不整合 (上記 4.2)
  2. Box TLS-SLL の過剰 overhead → 性能劣化 → workload timeout → 不正状態

影響範囲:

  • 確実: Larson benchmark (high alloc/free rate, multi-thread)
  • 潜在的: Production workload (長時間稼働, memory leak)

Part 5: 期待する成果物

5.1 設計の方向性

ChatGPT に求める回答:

  1. Header/Next 競合の解決策:

    • Best practice (他アロケータの実装)
    • Trade-off分析 (memory vs CPU)
    • 実装案 (in-band vs out-of-band)
  2. TLS SLL 同期の設計:

    • 適切な同期モデル (eventual vs strong)
    • Performance overhead の見積もり
    • 実装パターン (atomic, RCU, etc.)
  3. 学習層の改善:

    • PID制御の調整 (I/D項追加)
    • Convergence detection の手法
    • Production deployment 戦略
  4. 並行性の最適化:

    • Lock-free の適用範囲
    • Race condition 回避パターン
    • Testing strategy

5.2 具体的な実装案

期待する形式:

【提案】Header を Out-of-band 化

【根拠】
- jemalloc/mimalloc は chunk/page header を別領域管理
- In-band header は next pointer と競合 (C0/C7)
- Out-of-band なら競合なし、fast path 単純化可能

【設計】
SuperSlab に class_idx map 追加:
  uint8_t class_map[256];  // slab_idx → class_idx

Lookup:
  slab_idx = (ptr - ss->base) / SLAB_SIZE
  class_idx = ss->class_map[slab_idx]
  // Cost: 2 memory access (slab_idx calc + map lookup)
  // vs Current: 1 memory access (header read)

【Trade-off】
- Memory: +256B/SuperSlab (許容範囲)
- CPU: +1 memory access (~3-5サイクル)
- 利点: Next pointer と競合なし → Box TLS-SLL 単純化 → -50サイクル

【Net】+3サイクル (lookup) - 50サイクル (Box overhead) = -47サイクル (改善)

5.3 優先度付きロードマップ

期待する形式:

【P0 - 即座に修正】(1週間)
1. TLS SLL clear on slab reuse (防御的修正)
2. Periodic drain 間隔調整 (adaptive mode)

【P1 - 短期修正】(2-3週間)
3. Header out-of-band 化 (設計変更)
4. Box TLS-SLL 単純化 (性能回復)

【P2 - 中期改善】(1-2ヶ月)
5. PID制御調整 (I/D項追加)
6. Convergence detection 実装

【P3 - 長期最適化】(3ヶ月+)
7. NUMA awareness
8. Profile-Guided Optimization 統合

添付資料

関連ファイルパス

Layer 0 (Tiny Pool):

  • /mnt/workdisk/public_share/hakmem/core/hakmem_tiny.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_tiny_superslab.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/box/tls_sll_box.h
  • /mnt/workdisk/public_share/hakmem/core/tiny_region_id.h
  • /mnt/workdisk/public_share/hakmem/core/tiny_nextptr.h
  • /mnt/workdisk/public_share/hakmem/core/tiny_free_fast_v2.inc.h

Layer 1 (ACE):

  • /mnt/workdisk/public_share/hakmem/core/hakmem_ace.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_learner.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_pool.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_l25_pool.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_ace_controller.{c,h}

Layer 2 (Big Cache):

  • /mnt/workdisk/public_share/hakmem/core/hakmem_bigcache.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_batch.{c,h}

Layer 3 (Policy):

  • /mnt/workdisk/public_share/hakmem/core/hakmem_policy.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_p2.{c,h}
  • /mnt/workdisk/public_share/hakmem/core/hakmem_elo.{c,h}

調査レポート:

  • /mnt/workdisk/public_share/hakmem/docs/analysis/TLS_SLL_ARCHITECTURE_INVESTIGATION.md
  • /mnt/workdisk/public_share/hakmem/docs/status/PHASE_E3-1_SUMMARY.md
  • /mnt/workdisk/public_share/hakmem/BOX_THEORY_LAYER_DIAGRAM.txt
  • /mnt/workdisk/public_share/hakmem/REFACTOR_ARCHITECTURE_DIAGRAM.txt

以上