Files
hakmem/docs/status/PHASE_6.22_RESULTS_2025_10_24.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

13 KiB
Raw Blame History

Phase 6.22: SuperSlab 実装(基盤構築フェーズ)

日付: 2025-10-24 ステータス: Phase 6.22-A/B 完了 (基盤準備済み、未稼働) 目標: mimalloc-inspired SuperSlab architecture 実装 期待効果: +10-15% (Tiny 1T/4T) ※Phase 6.23 で稼働時


📋 Overview

Phase 6.22 では、mimalloc の Segment-Aligned Allocation 手法を参考に、hakmem Tiny Pool 用の SuperSlab アーキテクチャを実装しました。これは 2MB aligned memory 上に 32 個の 64KB slab を配置し、pointer → slab の高速変換1 AND 演算)を実現します。

Phase 6.22 分割実装

Sub-Phase 内容 ステータス
6.22-A SuperSlab 構造体定義 + 2MB allocator 完了
6.22-B Free path への SuperSlab 統合 完了(未稼働)
6.23 Allocation path 統合 + Per-thread queues 🔜 次回

🏗️ Phase 6.22-A: SuperSlab 基盤実装

実装内容

1. SuperSlab 構造体定義 (hakmem_tiny_superslab.h)

#define SUPERSLAB_SIZE    (2 * 1024 * 1024)  // 2MB (mimalloc-style)
#define SUPERSLAB_MASK    (SUPERSLAB_SIZE - 1)
#define SLAB_SIZE         (64 * 1024)        // 64KB per slab
#define SLABS_PER_SUPERSLAB 32               // 2MB / 64KB = 32

typedef struct TinySlabMeta {
    void*    freelist;       // Freelist head (8B)
    uint16_t used;           // Blocks currently used (2B)
    uint16_t capacity;       // Total blocks in slab (2B)
    uint32_t owner_tid;      // Owner thread ID (4B)
} TinySlabMeta;              // Total: 16B per slab

typedef struct SuperSlab {
    // Header (64B)
    uint64_t magic;          // 0x48414B4D454D5353 ("HAKMEMSS")
    uint8_t  size_class;     // 0-7 (8-64B)
    uint8_t  active_slabs;   // Number of active slabs (0-32)
    uint32_t slab_bitmap;    // 32-bit bitmap (1=active, 0=free)

    // Per-slab metadata (32 x 16B = 512B)
    TinySlabMeta slabs[32];

} __attribute__((aligned(64))) SuperSlab;

2. Fast Inline Functions (mimalloc-style)

// Get SuperSlab from pointer (1 AND operation)
static inline SuperSlab* ptr_to_superslab(void* p) {
    return (SuperSlab*)((uintptr_t)p & ~(uintptr_t)SUPERSLAB_MASK);
}

// Get slab index within SuperSlab (1 shift operation)
static inline int ptr_to_slab_index(void* p) {
    uintptr_t offset = (uintptr_t)p & SUPERSLAB_MASK;
    return (int)(offset >> 16);  // Divide by 64KB (2^16)
}

// Get slab metadata from pointer (2 operations)
static inline TinySlabMeta* ptr_to_slab_meta(void* p) {
    SuperSlab* ss = ptr_to_superslab(p);
    int idx = ptr_to_slab_index(p);
    return &ss->slabs[idx];
}

3. 2MB Aligned Allocator (hakmem_tiny_superslab.c)

SuperSlab* superslab_allocate(uint8_t size_class) {
    // 1. Try MAP_ALIGNED_SUPER (if available)
#ifdef MAP_ALIGNED_SUPER
    ptr = mmap(NULL, SUPERSLAB_SIZE, PROT_READ | PROT_WRITE,
               MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0);
#endif

    // 2. Fallback: Manual alignment
    size_t alloc_size = SUPERSLAB_SIZE * 2;  // 4MB
    void* raw = mmap(NULL, alloc_size, ...);

    // Align to 2MB boundary
    uintptr_t aligned_addr = (raw_addr + SUPERSLAB_MASK) & ~SUPERSLAB_MASK;

    // Unmap unused regions (prefix/suffix)
    munmap(prefix_region, prefix_size);
    munmap(suffix_region, suffix_size);

    // Initialize SuperSlab header
    ss->magic = SUPERSLAB_MAGIC;
    ss->size_class = size_class;
    ss->active_slabs = 0;
    ss->slab_bitmap = 0;

    return ss;
}

Makefile 統合

# Line 14
OBJS = ... hakmem_tiny_superslab.o ...

# Line 18
SHARED_OBJS = ... hakmem_tiny_superslab_shared.o ...

# Line 23
BENCH_HAKMEM_OBJS = ... hakmem_tiny_superslab.o ...

ビルド結果

$ make clean && make bench
...
========================================
Build successful!
========================================

Benchmark (Phase 6.21 比較)

Benchmark Phase 6.21 Phase 6.22-A 変化 備考
Tiny 1T 20.1 M/s 20.0 M/s -0.5% コード追加によるわずかな劣化
Tiny 4T 53.6 M/s 57.9 M/s +8.0% 🎉 予期しない改善!

驚きの発見: SuperSlab コードを追加しただけまだ使用していないで、Tiny 4T が +8% 向上! 推測: コードサイズ変化によるキャッシュライン配置の偶然の最適化。


🔧 Phase 6.22-B: SuperSlab Free Path 統合

実装内容

1. SuperSlab Fast Free Path (hakmem_tiny.c:863-875)

// Phase 6.22-B: SuperSlab fast free path
static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
    int slab_idx = ptr_to_slab_index(ptr);
    TinySlabMeta* meta = &ss->slabs[slab_idx];

    // Simple freelist push (no same-thread check for now)
    *(void**)ptr = meta->freelist;
    meta->freelist = ptr;
    meta->used--;
}

2. Free Function 統合 (hakmem_tiny.c:877-893)

void hak_tiny_free(void* ptr) {
    if (!ptr || !g_tiny_initialized) return;

    // Phase 6.22-B: Try SuperSlab fast path first
    SuperSlab* ss = ptr_to_superslab(ptr);
    if (ss && ss->magic == SUPERSLAB_MAGIC) {
        hak_tiny_free_superslab(ptr, ss);
        return;  // Fast path exit
    }

    // Fallback to Registry lookup (existing path)
    TinySlab* slab = hak_tiny_owner_slab(ptr);
    if (!slab) return;
    hak_tiny_free_with_slab(ptr, slab);
}

現在の動作

  • SuperSlab free path のコードは実装済み
  • SuperSlab allocation がまだ未実装のため、実際には実行されない
  • Registry ベースの allocation/free が継続動作中
  • Backward compatibility 維持

Benchmark (Phase 6.22-A 比較)

Benchmark Phase 6.22-A Phase 6.22-B 変化 備考
Tiny 1T 20.0 M/s 20.0 M/s 0% 変化なし(期待通り)
Tiny 4T 57.9 M/s 57.3 M/s -1% わずかな劣化(期待通り)

結果: SuperSlab free path は未実行のため、性能は横ばい(期待通り)。


📊 Performance Comparison

Phase 6.20 → 6.21 → 6.22 推移

Benchmark 6.20 6.21 6.22-A 6.22-B 変化 (6.20→6.22)
Tiny 1T 20.1 20.1 20.0 20.0 -0.5%
Tiny 4T 53.6 53.6 57.9 57.3 +6.9% 🎉
Mid 1T 3.86 3.86 3.87 - +0.3%
Mid 4T 8.36 8.37 8.33 - -0.4%
Large 1T 0.54 0.54 0.54 - 0%
Large 4T 1.27 1.27 1.27 - 0%

vs mimalloc (Phase 6.22-B)

Benchmark hakmem mimalloc 達成率
Tiny 1T 20.0 M/s 33.8 M/s 59%
Tiny 4T 57.3 M/s 76.5 M/s 75%

Phase 6.23 目標: Tiny 1T/4T で +10-15% → 達成率 65-70% / 82-86%


🎯 Technical Achievements

完了した項目

  1. SuperSlab 構造体設計

    • 2MB aligned memory layout
    • 32 x 64KB slab structure
    • Per-slab metadata (16B each)
    • Magic number validation
  2. 2MB Aligned Allocator

    • MAP_ALIGNED_SUPER サポート
    • Manual alignment fallback (4MB allocation)
    • Unused region unmapping
    • Global statistics tracking
  3. Fast Pointer Arithmetic

    • ptr_to_superslab(): 1 AND operation
    • ptr_to_slab_index(): 1 shift operation
    • ptr_to_slab_meta(): 2 operations total
  4. Free Path Integration

    • SuperSlab magic check
    • Fast freelist push
    • Registry fallback 維持
  5. Makefile Integration

    • Static/shared library builds
    • Benchmark integration
    • Dependency tracking

未実装項目 (Phase 6.23 へ)

  1. SuperSlab Allocation Path

    • refill_from_superslab() 実装
    • TLS active slab 統合
    • Initial slab initialization
  2. Same-Thread Fast Path

    • Owner TID check
    • Lock-free allocation/free
  3. Remote Free Handling

    • Per-thread remote queues
    • Cross-thread freelist
  4. Registry Migration

    • SuperSlab への完全移行
    • または Hybrid 運用

🚀 Next Steps: Phase 6.23

実装計画

Step 1: SuperSlab Allocation Path (1-2時間)

void* hak_tiny_alloc(size_t size) {
    int class_idx = SIZE_TO_CLASS[size >> 3];
    TinyTLS* tls = get_tls();

    // 1. Try TLS active slab
    TinySlab* active = tls->active_slab[class_idx];
    if (!active || !active->freelist) {
        // 2. Refill from SuperSlab
        active = refill_from_superslab(class_idx);
        if (!active) return NULL;
        tls->active_slab[class_idx] = active;
    }

    // 3. Pop from freelist
    void* block = active->freelist;
    active->freelist = *(void**)block;
    active->used++;
    return block;
}

TinySlab* refill_from_superslab(int class_idx) {
    // 1. Allocate new SuperSlab
    SuperSlab* ss = superslab_allocate(class_idx);
    if (!ss) return NULL;

    // 2. Initialize first slab
    uint32_t my_tid = (uint32_t)(uintptr_t)pthread_self();
    superslab_init_slab(ss, 0, g_class_sizes[class_idx], my_tid);

    // 3. Return slab metadata
    return convert_to_tinyslab(&ss->slabs[0]);
}

Step 2: Same-Thread Fast Path

void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
    int slab_idx = ptr_to_slab_index(ptr);
    TinySlabMeta* meta = &ss->slabs[slab_idx];

    // Same-thread check
    uint64_t my_tid = (uint64_t)(uintptr_t)pthread_self();
    if (meta->owner_tid == (uint32_t)my_tid) {
        // Fast path: Direct freelist push
        *(void**)ptr = meta->freelist;
        meta->freelist = ptr;
        meta->used--;
    } else {
        // Slow path: Remote free queue
        remote_free_superslab(ss, slab_idx, ptr);
    }
}

Step 3: Per-Thread Remote Queues

typedef struct RemoteFreeQueue {
    void* head;
    void* tail;
    uint32_t count;
} RemoteFreeQueue;

typedef struct TinyTLS {
    TinySlab* active_slab[8];
    RemoteFreeQueue remote_queue[8];  // Per size class
} TinyTLS;

期待される性能向上

Benchmark Phase 6.22-B Phase 6.23 目標 改善幅
Tiny 1T 20.0 M/s 22-23 M/s +10-15%
Tiny 4T 57.3 M/s 63-67 M/s +10-17%

vs mimalloc 予測

Benchmark Phase 6.23 目標 mimalloc 達成率
Tiny 1T 22-23 M/s 33.8 M/s 65-68%
Tiny 4T 63-67 M/s 76.5 M/s 82-88%

📝 Lessons Learned

1. Code Size が性能に影響

Phase 6.22-A でコードを追加しただけで Tiny 4T が +8% 向上した事例から、コードサイズ変化がキャッシュライン配置に影響を与えることを確認。

教訓: 性能測定は常にフルビルドで行うべき。Incremental build では予期しない性能変化が起こりうる。

2. Hybrid Approach の有効性

SuperSlab と Registry を並行運用することで、段階的な移行が可能。Backward compatibility を維持しながら新機能を実装できる。

教訓: Big Bang リライトではなく、Incremental migration が安全。

3. mimalloc の設計思想

Segment-Aligned Allocation は単なる最適化ではなく、アーキテクチャ全体の設計思想。Fast pointer arithmetic により、メタデータアクセスのコストを最小化。

教訓: "Fast path を極限まで速く" という mimalloc の哲学を学ぶ。


📂 File Changes Summary

新規ファイル

ファイル 行数 内容
hakmem_tiny_superslab.h 117 SuperSlab 構造体定義 + inline 関数
hakmem_tiny_superslab.c 231 2MB allocator 実装
docs/status/PHASE_6.22_PLAN_2025_10_24.md 467 Phase 6.22 実装計画
docs/status/PHASE_6.22B_PLAN_2025_10_24.md 278 Phase 6.22-B 実装計画

変更ファイル

ファイル 変更内容
Makefile hakmem_tiny_superslab.o 追加
hakmem_tiny.c SuperSlab free path 統合 (lines 863-893)

合計

  • 新規: 4 ファイル, 1093 行
  • 変更: 2 ファイル, ~20 行
  • Total: 約 1100 行の追加

🎉 Conclusion

Phase 6.22 では、mimalloc の Segment-Aligned Allocation 手法を参考に、SuperSlab アーキテクチャの基盤構築を完了しました。

主な成果

  1. 2MB aligned SuperSlab allocator 実装
  2. Fast pointer arithmetic (1-2 操作)
  3. Free path への SuperSlab 統合
  4. Backward compatibility 維持
  5. Tiny 4T で +7% 改善(副次効果)

次のステップ

Phase 6.23 で SuperSlab allocation path を実装し、+10-15% の性能向上を目指します。


作成日: 2025-10-24 12:05 JST 次のフェーズ: Phase 6.23 (SuperSlab Allocation + Per-thread Queues) 目標: Tiny 1T/4T で mimalloc の 65-88% 達成