Files
hakmem/docs/design/TINY_3LAYER_ARCHITECTURE.md
Moe Charm (CI) 52386401b3 Debug Counters Implementation - Clean History
Major Features:
- Debug counter infrastructure for Refill Stage tracking
- Free Pipeline counters (ss_local, ss_remote, tls_sll)
- Diagnostic counters for early return analysis
- Unified larson.sh benchmark runner with profiles
- Phase 6-3 regression analysis documentation

Bug Fixes:
- Fix SuperSlab disabled by default (HAKMEM_TINY_USE_SUPERSLAB)
- Fix profile variable naming consistency
- Add .gitignore patterns for large files

Performance:
- Phase 6-3: 4.79 M ops/s (has OOM risk)
- With SuperSlab: 3.13 M ops/s (+19% improvement)

This is a clean repository without large log files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 12:31:14 +09:00

9.5 KiB
Raw Blame History

Tiny Pool 3-Layer Architecture Design

日付: 2025-11-01 目的: 6-7層 → 3層への大胆なシンプル化 根拠: ChatGPT Pro UltraThink Response + 性能計測


📊 現状の問題

計測結果 (Baseline)

Metric Tiny Hot Random Mixed
Throughput 179 M ops/s 21.6 M ops/s
Instructions/op 100 412
目標 instructions/op 20-30 100-150
削減率 70-80% 60-75%

問題: mimalloc (推定 10-20 insns/op) の 5-10倍 のオーバーヘッド


🏗️ 現在のアーキテクチャ (6-7層)

void* hak_tiny_alloc(size_t size) {
    class_idx = hak_tiny_size_to_class(size);

    // Layer 1: HAKMEM_TINY_BENCH_FASTPATH (ベンチ専用)
    #ifdef HAKMEM_TINY_BENCH_FASTPATH
        if (g_tls_sll_head[class_idx]) return pop_sll();
        if (g_tls_mags[class_idx].top > 0) return pop_mag();
    #endif

    // Layer 2: TinyHotMag (class ≤ 2)
    if (g_hotmag_enable && class_idx <= 2) {
        if (hotmag_pop()) return p;
    }

    // Layer 3: g_hot_alloc_fn (専用関数)
    if (g_hot_alloc_fn[class_idx]) {
        switch (class_idx) {
            case 0: return tiny_hot_pop_class0();
            ...
        }
    }

    // Layer 4: tiny_fast_pop (Fast Head SLL)
    if (tiny_fast_pop()) return p;

    // Layer 5-7: Slow path (Magazine, Slab, Bitmap, etc.)
    return hak_tiny_alloc_slow();
}

問題:

  1. ✗ 重複する層 (Layer 1-4 はすべて TLS キャッシュ)
  2. ✗ 条件分岐が多すぎる
  3. ✗ 関数呼び出しオーバーヘッド
  4. ✗ 複数のデータ構造 (sll, hotmag, fast_pop, magazine)

🎯 新アーキテクチャ (3層)

Layer 1: TLS Bump Allocator (8B/16B/32B専用)

目的: 超高速パス、2-3 instructions/op

データ構造:

// Per-class bump allocator (hot classes only: 8B, 16B, 32B)
typedef struct {
    void* bcur;   // Current bump pointer
    void* bend;   // Bump end
} TinyBump;

static __thread TinyBump g_tiny_bump[3];  // class 0, 1, 2

アロケーション:

static inline void* tiny_bump_alloc_8B(void) {
    void* old = g_tiny_bump[0].bcur;
    void* new_cur = (char*)old + 8;
    if (likely(new_cur <= g_tiny_bump[0].bend)) {
        g_tiny_bump[0].bcur = new_cur;
        return old;
    }
    return NULL;  // fallback to Layer 2
}

// 16B, 32B も同様

期待命令数: 2-3 instructions

  • load bcur
  • add 8/16/32
  • compare bcur <= bend
  • store bcur (条件付き)
  • return

リフィル (Layer 3 から):

void tiny_bump_refill(int class_idx, void* base, size_t size) {
    g_tiny_bump[class_idx].bcur = base;
    g_tiny_bump[class_idx].bend = (char*)base + size;
}

Layer 2: TLS Small Magazine (全クラス)

目的: 中速パス、5-10 instructions/op

データ構造:

typedef struct {
    void* items[128];  // 固定サイズ 128
    int top;           // スタックポインタ
} TinySmallMag;

static __thread TinySmallMag g_tiny_small_mag[TINY_NUM_CLASSES];

アロケーション:

static inline void* small_mag_pop(int class_idx) {
    TinySmallMag* mag = &g_tiny_small_mag[class_idx];
    int t = mag->top;
    if (likely(t > 0)) {
        mag->top = t - 1;
        return mag->items[t - 1];
    }
    return NULL;  // fallback to Layer 3
}

期待命令数: 5-10 instructions

  • load mag->top
  • compare top > 0
  • decrement top
  • load mag->items[top - 1]
  • store mag->top
  • return

フリー:

static inline bool small_mag_push(int class_idx, void* ptr) {
    TinySmallMag* mag = &g_tiny_small_mag[class_idx];
    int t = mag->top;
    if (likely(t < 128)) {
        mag->items[t] = ptr;
        mag->top = t + 1;
        return true;
    }
    return false;  // overflow, drain to Layer 3
}

サイズ計算 (L1 cache):

  • 8B class: 128 * 8B = 1KB
  • 16B class: 128 * 8B (pointer) = 1KB
  • 32B class: 128 * 8B = 1KB
  • Total per thread: ~8KB (全クラス分) → L1 32KB の 25% → OK

Layer 3: Slow Path (Slab管理)

目的: 低頻度パス、リフィル・Slab割り当て

処理:

  1. Magazine リフィル: Layer 2 の Small Magazine を補充
  2. Bump リフィル: Layer 1 の Bump を補充 (class 0-2)
  3. Slab 割り当て: 新しい Slab を割り当て
  4. Global pool からの取得

関数:

void* tiny_alloc_slow(int class_idx) {
    // Step 1: Try refill Small Magazine from large magazine
    if (large_mag_refill_to_small(class_idx, 64)) {
        return small_mag_pop(class_idx);
    }

    // Step 2: Try refill from Slab
    if (slab_refill_to_small(class_idx, 64)) {
        return small_mag_pop(class_idx);
    }

    // Step 3: Allocate new Slab
    TinySlab* slab = allocate_new_slab(class_idx);
    if (slab) {
        // Refill both bump (class 0-2) and magazine
        if (class_idx <= 2) {
            tiny_bump_refill(class_idx, slab->base, slab->total_count * g_tiny_class_sizes[class_idx]);
            return tiny_bump_alloc(class_idx);
        } else {
            slab_refill_to_small(class_idx, 64);
            return small_mag_pop(class_idx);
        }
    }

    return NULL;  // OOM
}

🔄 メインアロケーション関数

void* hak_tiny_alloc(size_t size) {
    // Size to class
    int class_idx = hak_tiny_size_to_class(size);
    if (class_idx < 0) return NULL;  // > 1KB

    // === Layer 1: TLS Bump (hot classes 0-2: 8B/16B/32B) ===
    if (class_idx <= 2) {
        void* p;
        switch (class_idx) {
            case 0: p = tiny_bump_alloc_8B(); break;
            case 1: p = tiny_bump_alloc_16B(); break;
            case 2: p = tiny_bump_alloc_32B(); break;
        }
        if (likely(p)) return p;
    }

    // === Layer 2: TLS Small Magazine (all classes) ===
    void* p = small_mag_pop(class_idx);
    if (likely(p)) return p;

    // === Layer 3: Slow path ===
    return tiny_alloc_slow(class_idx);
}

期待命令数:

  • Hot path (Layer 1 hit): 5-8 instructions (switch + bump + return)
  • Medium path (Layer 2 hit): 15-20 instructions (switch + mag_pop + return)
  • Cold path (Layer 3): 50-100+ instructions

平均命令数 (Tiny Hot, 推定):

  • Layer 1 hit rate: 95% → 95% * 8 = 7.6 insns
  • Layer 2 hit rate: 4% → 4% * 20 = 0.8 insns
  • Layer 3 hit rate: 1% → 1% * 100 = 1.0 insns
  • Total: ~9.4 insns/op (現在の 100 から 90% 削減)

🗑️ 削除する機能

完全削除

  1. ✂️ HAKMEM_TINY_BENCH_FASTPATH - ベンチ専用、本番不要
  2. ✂️ TinyHotMag (g_tls_hot_mag) - Layer 1 Bump で代替
  3. ✂️ g_hot_alloc_fn - Layer 1 Bump で代替
  4. ✂️ tiny_fast_pop (g_fast_head) - Layer 2 Small Magazine で代替
  5. ✂️ 大きい Magazine (2048 items) - Layer 2 (128 items) に統一

保持 (Layer 3 で使用)

  1. Slab 管理 (bitmap, mini-mag)
  2. Registry (O(1) lookup)
  3. Remote free queue
  4. Background spill/drain

📈 期待効果

Tiny Hot (64B, class 2)

Metric 現在 目標 改善
Instructions/op 100 10-15 85-90%削減
Throughput 179 M/s 240-250 M/s +35-40%
Layer 1 hit rate - 95%+ -

Random Mixed (8-128B)

Metric 現在 目標 改善
Instructions/op 412 100-150 60-75%削減
Throughput 21.6 M/s 23-24 M/s +10%
Layer 1+2 hit rate - 98%+ -

🛠️ 実装ステップ

Phase 1: 新 Layer 実装

  1. TLS Bump (core/hakmem_tiny_bump.inc.h)

    • データ構造定義
    • tiny_bump_alloc_8B/16B/32B()
    • tiny_bump_refill()
    • 所要時間: 1-2時間
  2. Small Magazine (core/hakmem_tiny_smallmag.inc.h)

    • データ構造定義
    • small_mag_pop/push()
    • 所要時間: 1-2時間
  3. 新メイン関数 (core/hakmem_tiny_alloc.inc 書き換え)

    • シンプルな 3-layer 構造
    • 所要時間: 1時間

Phase 2: 古い Layer 削除

  1. コンパイル確認

    • 削除する機能を #if 0 で無効化
    • ビルド成功確認
    • 所要時間: 30分
  2. ベンチマーク実行

    • Tiny Hot, Random Mixed 実行
    • perf stat 計測
    • 所要時間: 30分

Phase 3: 評価・調整

  1. 結果評価

    • 目標達成?
    • パフォーマンス低下?
    • 所要時間: 30分
  2. 調整 or ロールバック

    • 成功 → 古いコード完全削除、コミット
    • 失敗 → ロールバック、原因分析
    • 所要時間: 1-2時間

総所要時間: 6-8時間 (1日作業)


⚠️ リスクと対策

リスク 1: パフォーマンス低下

対策:

  • ベースライン計測済み
  • 各ステップで perf stat 実行
  • 低下時は即ロールバック

リスク 2: 機能の欠落

対策:

  • Remote free は保持 (Layer 3)
  • Background drain は保持
  • テスト実行で確認

リスク 3: L1 cache 圧迫

対策:

  • Small Magazine は合計 8KB (L1 32KB の 25%)
  • Bump は 24B (3 classes * 8B) のみ
  • 計測で確認

📋 チェックリスト

実装前

  • ベースライン計測完了
  • 設計ドキュメント作成
  • Git ブランチ作成

実装中

  • TLS Bump 実装
  • Small Magazine 実装
  • 新メイン関数実装
  • 古いコード無効化
  • ビルド成功

実装後

  • ベンチマーク実行
  • perf stat 計測
  • 目標達成確認
  • コミット or ロールバック

次のアクション: Git ブランチ作成 → TLS Bump 実装開始