Files
hakmem/CURRENT_TASK.md
Moe Charm (CI) 5b36c1c908 Phase 26: Front Gate Unification - Tiny allocator fast path (+12.9%)
Implementation:
- New single-layer malloc/free path for Tiny (≤1024B) allocations
- Bypasses 3-layer overhead: malloc → hak_alloc_at (236 lines) → wrapper → tiny_alloc_fast
- Leverages Phase 23 Unified Cache (tcache-style, 2-3 cache misses)
- Safe fallback to normal path on Unified Cache miss

Performance (Random Mixed 256B, 100K iterations):
- Baseline (Phase 26 OFF): 11.33M ops/s
- Phase 26 ON: 12.79M ops/s (+12.9%)
- Prediction (ChatGPT): +10-15% → Actual: +12.9% (perfect match!)

Bug fixes:
- Initialization bug: Added hak_init() call before fast path
- Page boundary SEGV: Added guard for offset_in_page == 0

Also includes Phase 23 debug log fixes:
- Guard C2_CARVE logs with #if !HAKMEM_BUILD_RELEASE
- Guard prewarm logs with #if !HAKMEM_BUILD_RELEASE
- Set Hot_2048 as default capacity (C2/C3=2048, others=64)

Files:
- core/front/malloc_tiny_fast.h: Phase 26 implementation (145 lines)
- core/box/hak_wrappers.inc.h: Fast path integration (+28 lines)
- core/front/tiny_unified_cache.h: Hot_2048 default
- core/tiny_refill_opt.h: C2_CARVE log guard
- core/box/ss_hot_prewarm_box.c: Prewarm log guard
- CURRENT_TASK.md: Phase 26 completion documentation

ENV variables:
- HAKMEM_FRONT_GATE_UNIFIED=1 (enable Phase 26, default: OFF)
- HAKMEM_TINY_UNIFIED_CACHE=1 (Phase 23, required)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 05:29:08 +09:00

54 KiB
Raw Blame History

CURRENT TASK (Phase 1426 Snapshot) Tiny / Mid / ExternalGuard / Unified Cache / Front Gate

Last Updated: 2025-11-17 Owner: ChatGPT → Phase 23/25/26 実装完了: Claude Code Size: 約 350 行Claude 用コンテキスト簡略版)


🎉 Phase 26: Front Gate Unification - 完了 (2025-11-17)

成果: Random Mixed 256B ベンチマーク +12.9% 改善 (11.33M → 12.79M ops/s)

Phase 26: Front Gate Unification (ChatGPT先生提案)

  • 設計: malloc → hak_alloc_at (236行) → wrapper → tiny_alloc_fast の 3層オーバーヘッド削減
  • 実装: core/front/malloc_tiny_fast.h + core/box/hak_wrappers.inc.h 統合
  • 戦略: Tiny範囲≤1024B専用の単層直行経路、Phase 23 Unified Cache 活用
  • ENV: HAKMEM_FRONT_GATE_UNIFIED=1 でデフォルトOFF → 本番投入推奨

Phase 26 実装詳細

malloc_tiny_fast() (alloc fast path):

1. size  class_idx (inline table lookup, 1-2 instructions)
2. unified_cache_pop_or_refill(class_idx) (Phase 23 tcache, 2-3 cache misses)
3. Write header + return USER pointer (2-3 instructions)
Total: 8-10 instructions (vs 3-layer cascade: 236 lines routing + diagnostics)

free_tiny_fast() (free fast path):

1. Page boundary guard (offset_in_page == 0  return 0)
2. Read header + validate Tiny magic (0xa0-0xa7)
3. unified_cache_push(class_idx, base) (Phase 23 tcache, 2-3 cache misses)
Total: 6-8 instructions (vs classify_ptr + hak_free_at routing)

Phase 26 修正したバグ

  1. 初期化バグ: Phase 26 fast path が hak_init() をバイパス → if (!g_initialized) hak_init() 追加
  2. ページ境界SEGV: free_tiny_fast() がページ先頭 (offset==0) で前ページ読み → ガード追加
    uintptr_t off = (uintptr_t)ptr & 0xFFFu;
    if (off == 0) return 0;  // Page-aligned → 通常 free 経路へ
    

A/B ベンチマーク結果 (Random Mixed 256B, 100K iterations)

Configuration Run 1 Run 2 Run 3 Average vs Baseline
Phase 26 OFF 11.21M 11.02M 11.76M 11.33M ops/s Baseline
Phase 26 ON 13.21M 12.55M 12.62M 12.79M ops/s +12.9% 🎯

ChatGPT先生の予測: +10-15% (3層オーバーヘッド削減による改善) 実測結果: +12.9%予測ど真ん中! 🎯

本番推奨設定 (Phase 23 + Phase 26 組み合わせ)

export HAKMEM_TINY_UNIFIED_CACHE=1     # Phase 23: Hot_2048がデフォルト
export HAKMEM_FRONT_GATE_UNIFIED=1     # Phase 26: Front Gate Unification
./out/release/bench_random_mixed_hakmem
# Expected: 12.79M ops/s (+27.8% vs Phase 23前のbaseline 10.0M ops/s)

主要ファイル:

  • core/front/malloc_tiny_fast.h - Phase 26 single-layer malloc/free implementation
  • core/box/hak_wrappers.inc.h:128-143 - Phase 26 fast path integration (malloc)
  • core/box/hak_wrappers.inc.h:179-190 - Phase 26 fast path integration (free)

🎉 Phase 23/25: Unified Frontend Cache - 完了 (2025-11-17)

成果: Random Mixed 256B ベンチマーク +7.3% 改善 (10.58M → 11.35M ops/s)

Phase 23: Unified Cache Implementation

  • 設計: tcache-style single-layer frontend (Ring → FastCache → SFC → SLL の 4 層を 1 層に統合)
  • 実装: core/front/tiny_unified_cache.{h,c} - Array-based ring buffer (2-3 cache misses)
  • 統合: Alloc path (tiny_alloc_fast.inc.h:621-633) + Free path (hak_free_api.inc.h)
  • ENV: HAKMEM_TINY_UNIFIED_CACHE=1 でデフォルトOFF → Hot_2048設定で本番投入

Phase 23 Capacity Optimization (Hot_2048)

  • Task Agent: 10 configurations × 3 runs = 35 benchmarks
  • 最適設定: C2/C3 (128B/256B) = 2048 slots, 他 = 64 slots
  • 根拠: Hot-class優先戦略が+6.2%の追加改善vs All_128
  • メモリ: ~1.1MB cache overhead (C2/C3 に集中配置)

Phase 25-A: Header Read Optimization (+2.2%)

  • 削減: FG_DOMAIN_TINY の重複 header read を除去
  • L1 hit: 2回目の header read は L1 cache hit (~1 cycle) → 効果限定的

Phase 25-B-1: Promote-on-Full (REVERTED, -4.0%)

  • 失敗: Smart promotion logic が overhead > benefit
  • 教訓: Clever ≠ Fast、incremental最適化は限界に達した

Debug Log修正 (性能改善)

  • 修正箇所: core/tiny_refill_opt.h:316-326, core/box/ss_hot_prewarm_box.c:143-146
  • 問題: [C2_CARVE] / [BOX_SS_HOT_PREWARM] が Release build で常時出力
  • 解決: #if !HAKMEM_BUILD_RELEASE で囲み、stderr負荷を除去

本番推奨設定

export HAKMEM_TINY_UNIFIED_CACHE=1  # Hot_2048がデフォルトC2/C3=2048, 他=64
./out/release/bench_random_mixed_hakmem

次の戦略: Phase 23でfrontend最適化は限界、Phase 12 Shared SuperSlab Pool (backend根本解決) へ進む


1. 全体の現在地(どこまで終わっているか)

  • Tiny (01023B)

    • NEW 3-layer frontbump / small_mag / slow安定。
    • TinyHeapV2: 「alloc フロント+統計」は実装済みだが、実運用は C2/C3 を UltraHot に委譲
    • TinyUltraHotPhase 14:
      • C2/C316B/32B専用 L0 ultra-fast pathStealing モデル)。
      • 固定サイズベンチで +16〜36% 改善、hit 率 ≈ 100%。
    • Box 分離Phase 15:
      • free ラッパが外部ポインタまで hak_free_at に投げていた問題を修正。
      • BenchMetaslots など)→ 直接 __libc_free、CoreAllocTiny/Midhak_free_at の二段構えに整理。
  • Mid / PoolTLS1KB32KB

    • PoolTLS Phase 完了Mid-Large MT ベンチ)
      • ~10.6M ops/ssystem malloc より速い構成あり)。
      • lock contentionfutex 68%)を lock-free MPSC + bind box で大幅削減。
    • GAP 修正Tiny 1023B / Mid 1KB〜:
      • TINY_MAX_SIZE=1023 / MID_MIN_SIZE=1024 で 1KB8KB の「誰も扱わない帯」は解消済み。
  • Shared SuperSlab PoolPhase 12 SP-SLOT Box

    • 1 SuperSlab : 多 class 共有 + SLOT_UNUSED/ACTIVE/EMPTY 追跡。
    • SuperSlab 数: 877 → 72-92%、mmap/munmap: -48%、Throughput: +131%。
    • Lock contention P0-5 まで実装済みStage 2 lock-free claiming
  • ExternalGuardPhase 15

    • UNKNOWN ポインタTiny/Pool/Mid/L25/registry どこでも捕まらないもの)を最後の箱で扱う。
    • 挙動:
      • hak_super_lookup など全て miss → mincore でページ確認 → 原則「解放せず leak 扱い(安全優先)」。
    • Phase 15 修正で:
      • BenchMeta のポインタを CoreAlloc に渡さなくなり、UNKNOWN 呼び出し回数が激減。
      • mincore の CPU 負荷もベンチではほぼ無視できるレベルまで縮小。

2. Tiny 性能の現状Phase 1415 時点)

2.1 Fixed-size Tiny ベンチHAKMEM vs System

Phase 21-1: Ring Cache Implementation (C2/C3/C5) (2025-11-16) 🎯

  • Goal: Eliminate pointer chasing in TLS SLL by using array-based ring buffer cache
  • Strategy: 3-layer hierarchy (Ring L0 → SLL L1 → SuperSlab L2)
  • Implementation:
    • Added TinyRingCache struct with power-of-2 ring buffer (128 slots default)
    • Implemented ring_cache_pop/push for ultra-fast alloc/free (1-2 instructions)
    • Extended to C2 (32B), C3 (64B), C5 (256B) size classes
    • ENV variables: HAKMEM_TINY_HOT_RING_ENABLE=1, HAKMEM_TINY_HOT_RING_C2/C3/C5=128
  • Results (bench_random_mixed_hakmem 500K, 256B workload):
    • Baseline (Ring OFF): 20.18M ops/s
    • C2/C3 Ring: 21.15M ops/s (+4.8% improvement)
    • C2/C3/C5 Ring: 21.18M ops/s (+5.0% total improvement)
  • Analysis:
    • C2/C3 provide most of the gain (small sizes are hottest)
    • C5 addition provides marginal benefit (+0.03M ops/s)
    • Implementation complete and stable
  • Files Modified:
    • core/front/tiny_ring_cache.h/c - Ring buffer implementation
    • core/tiny_alloc_fast.inc.h - Alloc path integration
    • core/tiny_free_fast_v2.inc.h - Free path integration (line 154-160)

Phase 21-1-D: Ring Cache Default ON (2025-11-16) 🚀

  • Goal: Enable Ring Cache by default for production use (remove ENV gating)
  • Implementation: 1-line change in core/front/tiny_ring_cache.h:72
    • Changed logic: g_enable = (e && *e == '0') ? 0 : 1; // DEFAULT: ON
    • ENV=0 disables, ENV unset or ENV=1 enables
  • Results (bench_random_mixed_hakmem 500K, 256B workload, 3-run average):
    • Ring ON (default): 20.31M ops/s (baseline)
    • Ring OFF (ENV=0): 19.30M ops/s
    • Improvement: +5.2% (+1.01M ops/s)
  • Impact: Ring Cache now active in all builds without manual ENV configuration

Performance Bottleneck Analysis (Task-sensei Report, 2025-11-16) 🔍

Root Cause: Cache Misses (6.6x worse than System malloc)

  • L1 D-cache miss rate: HAKMEM 5.15% vs System 0.78% → 6.6x higher
  • IPC (instructions/cycle): HAKMEM 0.52 vs System 1.43 → 2.75x worse
  • Branch miss rate: HAKMEM 11.86% vs System 4.77% → 2.5x higher
  • Per-operation cost: HAKMEM 8-10 cache misses vs System 2-3 cache misses

Problem: 4-5 Layer Frontend Cascade

Random Mixed allocation flow:
  Ring (L0) miss → FastCache (L1) miss → SFC (L2) miss → TLS SLL (L3) miss → SuperSlab refill (L4)
  = 8-10 cache misses per allocation (each layer = 2 misses: head + next pointer)

System malloc tcache: 2-3 cache misses (single-layer array-based bins)

Improvement Roadmap (Target: 48-77M ops/s, System比 53-86%):

  1. P1 (Done): Ring Cache default ON → +5.2% (20.3M ops/s)
  2. P2 (Next): Unified Frontend Cache (flatten 4-5 layers → 1 layer) → +50-100% (30-40M expected)
  3. P3: Adaptive refill optimization → +20-30%
  4. P4: Branchless dispatch table → +10-15%
  5. P5: Metadata locality optimization → +15-20%

Conservative Target: 48M ops/s (+136% vs current, 53% of System) Optimistic Target: 77M ops/s (+279% vs current, 86% of System)


Phase 22: Lazy Per-Class Initialization (2025-11-16) 🚀

  • Goal: Cold-start page faultを削減 (ChatGPT分析: hak_tiny_init() → 94.94% of page faults)
  • Strategy: Eager init (全8クラス初期化) → Lazy init (使用クラスのみ初期化)
  • Results (bench_random_mixed_hakmem 500K, 256B workload):
    • Cold-start: 18.1M ops/s (Phase 21-1: 16.2M) → +12% improvement
    • Steady-state: 25.5M ops/s (Phase 21-1: 26.1M) → -2.3% (誤差範囲)
  • Key Achievement: hak_tiny_init.part.0 完全削除、未使用クラスのpage touchを回避
  • Remaining Bottleneck: SuperSlab allocation時のmemset page fault (42.40%)

📊 PERFORMANCE MAP (2025-11-16) - 全体性能俯瞰 🗺️

ベンチマーク自動化スクリプト: scripts/bench_performance_map.sh 最新結果: bench_results/performance_map/20251116_095827/

🎯 固定サイズ (16-1024B) - Tiny層の現実

Size System HAKMEM Ratio Status
16B 118.6M 50.0M 42.2% Slow
32B 103.3M 49.3M 47.7% Slow
64B 104.3M 49.2M 47.1% Slow
128B 74.0M 51.8M 70.0% ⚠️ Gap
256B 115.7M 36.2M 31.3% Slow
512B 103.5M 41.5M 40.1% Slow
1024B 96.0M 47.8M 49.8% Slow

発見:

  • 128Bのみ 70% (唯一Gap範囲) - 他は全て50%未満
  • 256Bが最悪 31.3% - Phase 22で18.1M → 36.2Mに改善したが、systemの1/3に留まる
  • 小サイズ (16-64B) 42-47% - UltraHot経由でも system の半分

🌀 Random Mixed (128B-1KB)

Allocator ops/s vs System
System 90.2M 100% (baseline)
Mimalloc 117.5M 130% 🏆 (systemより速い)
HAKMEM 21.1M 23.4% (mimallocの1/5.5)

衝撃的発見:

  • Mimallocは system より 30%速い
  • HAKMEMは mimalloc の 1/5.5 - 巨大なギャップ

💥 CRITICAL ISSUES - Mid-Large / MT層が完全破壊

Mid-Large MT (8-32KB): CRASHED (コアダンプ)

  • 原因: hkm_ace_alloc が 33KB allocation で NULL返却
  • 結果: free(): invalid pointer → クラッシュ
  • Mimalloc: 40.2M ops/s (system の 449%)
  • HAKMEM: 0 ops/s (動作不能)

VM Mixed: CRASHED (コアダンプ)

  • System: 957K ops/s
  • HAKMEM: 0 ops/s

Larson (MT churn): SEGV

  • System: 3.4M ops/s
  • Mimalloc: 3.4M ops/s
  • HAKMEM: 0 ops/s

🔧 Mid-Large Crash FIX (2025-11-16)

Root Cause (ChatGPT分析):

  • classify_ptr() が AllocHeader (Mid/Large mmap allocations) をチェックしていない
  • Free wrapper が PTR_KIND_MID_LARGE ケースを処理していない
  • 結果: Mid-Large ポインタが PTR_KIND_UNKNOWN__libc_free()free(): invalid pointer

修正内容:

  1. classify_ptr() に AllocHeader チェック追加 (core/box/front_gate_classifier.c:256-271)
    • hak_header_from_user() + hak_header_validate() で HAKMEM_MAGIC 確認
    • ALLOC_METHOD_MMAP/POOL/L25_POOLPTR_KIND_MID_LARGE 返却
  2. Free wrapper に PTR_KIND_MID_LARGE ケース追加 (core/box/hak_wrappers.inc.h:181)
    • is_hakmem_owned = 1 で HAKMEM 管轄として処理

修正結果:

  • Mid-Large MT (8-32KB): 0 → 10.5M ops/s (System 8.7M = 120%) 🏆
  • VM Mixed: 0 → 285K ops/s (System 939K = 30.4%)
  • クラッシュ完全解消、Mid-Large で system malloc を 20% 上回る

残存課題:

  • random_mixed: SEGV (AllocHeader読み込みでページ境界越え)
  • Larson: SEGV継続 (Tiny 8-128B 領域、別原因)

🔧 random_mixed Crash FIX (2025-11-16)

Root Cause:

  • Mid-Large fix で追加した classify_ptr() の AllocHeader check が unsafe
  • AllocHeader = 40 bytes → ptr - 40 がページ境界越えると SEGV
  • 例: ptr = 0x7ffff6a00000 (page-aligned) → header at 0x7ffff69fffd8 (別ページ、unmapped)

修正内容 (core/box/front_gate_classifier.c:263-266):

// Safety check: Need at least HEADER_SIZE (40 bytes) before ptr
uintptr_t offset_in_page_for_hdr = (uintptr_t)ptr & 0xFFF;
if (offset_in_page_for_hdr >= HEADER_SIZE) {
    // Safe to read AllocHeader (won't cross page boundary)
    AllocHeader* hdr = hak_header_from_user(ptr);
    ...
}

修正結果:

  • random_mixed: SEGV → 1.92M ops/s
  • Single-thread workloads 完全修復

🔧 Larson MT Crash FIX (2025-11-16)

2-Layer Problem Structure:

Layer 1: Cross-thread Free (TLS SLL Corruption)

  • Root Cause: Block allocated by Thread A, freed by Thread B → pushed to B's TLS SLL
    • B allocates the block → metadata still points to A's SuperSlab → corruption
    • Poison values (0xbada55bada55bada) in TLS SLL → SEGV in tiny_alloc_fast()
  • Fix (core/tiny_free_fast_v2.inc.h:176-205):
    • Made cross-thread check ALWAYS ON (removed ENV gating)
    • Check owner_tid_low on every free, route cross-thread to remote queue via tiny_free_remote_box()
  • Status: FIXED - TLS SLL corruption eliminated

Layer 2: SP Metadata Capacity Limit

  • Root Cause: [SP_META_CAPACITY_ERROR] Exceeded MAX_SS_METADATA_ENTRIES=2048
    • Larson rapid churn workload → 2048+ SuperSlabs → registry exhaustion → hang
  • Fix (core/hakmem_shared_pool.h:122-126):
    • Increased MAX_SS_METADATA_ENTRIES from 2048 → 8192 (4x capacity)
  • Status: FIXED - Larson completes successfully

Results (10 seconds, 4 threads):

  • Before: 4.2TB virtual memory, 65,531 mappings, indefinite hang (kill -9 required)
  • After: 6.7GB virtual (-99.84%), 424MB RSS, completes in 10-18 seconds
  • Throughput: 7,387-8,499 ops/s (0.014% of system malloc 60.6M)

Layer 3: Performance Optimization (IN PROGRESS)

  • Cross-thread check adds SuperSlab lookup on every free (20-50 cycles overhead)
  • Drain Interval Tuning (2025-11-16):
    • Baseline (drain=2048): 7,663 ops/s
    • Moderate (drain=1024): 8,514 ops/s (+11.1%)
    • Aggressive (drain=512): Core dump (too aggressive, causes crash)
  • Recommendation: export HAKMEM_TINY_SLL_DRAIN_INTERVAL=1024 for stable +11% gain
  • Remaining Work: LRU policy tuning (MAX_CACHED, MAX_MEMORY_MB, TTL_SEC)
  • Goal: Improve from 0.014% → 80% of system malloc (currently 0.015% with drain=1024)

📈 Summary (Performance Map 2025-11-16 17:15)

修正後の全体結果:

  • Competitive (≥80%): 0/10 benchmarks (0%)
  • ⚠️ Gap (50-80%): 1/10 benchmarks (10%) ← 64B固定のみ 53.6%
  • Slow (<50%): 9/10 benchmarks (90%)

主要ベンチマーク:

  1. Fixed-size (16-1024B): 38.5-53.6% of system (64B が最良)
  2. Random Mixed (128-1KB): 19.4M ops/s (24.0% of system)
  3. Mid-Large MT (8-32KB): 891K ops/s (12.1% of system, crash 修正済み )
  4. VM Mixed: 275K ops/s (30.7% of system, crash 修正済み )
  5. Larson (MT churn): 7.4-8.5K ops/s (0.014% of system, crash 修正済み , 性能最適化は Layer 3 で対応予定)

優先課題 (2025-11-16 更新):

  1. 完了: Mid-Large crash 修復 (classify_ptr + AllocHeader check)
  2. 完了: VM Mixed crash 修復 (Mid-Large fix で解消)
  3. 完了: random_mixed crash 修復 (page boundary check)
  4. 🔴 P0: Larson SP metadata limit 拡大 (2048 → 4096-8192)
  5. 🟡 P1: Fixed-size 性能改善 (38-53% → 目標 80%+)
  6. 🟡 P1: Random Mixed 性能改善 (24% → 目標 80%+)
  7. 🟡 P1: Mid-Large MT 性能改善 (12% → 目標 80%+, mimalloc 449%が参考値)

bench_fixed_size_hakmem / bench_fixed_size_systemworkset=128, 500K iterations 相当)

Size HAKMEM (Phase 15) System malloc 比率
128B ~16.6M ops/s ~90M ops/s ~18.5%
256B ~16.2M ops/s ~89.6M ops/s ~18.1%
512B ~15.0M ops/s ~90M ops/s ~16.6%
1024B ~15.1M ops/s ~90M ops/s ~16.8%

状態:

  • クラッシュは完全解消workset=64/128 で長尺 500K iter も安定)。
  • Tiny UltraHot + 学習層 + ExternalGuard の組み合わせは「正しさ」は OK。
  • 性能は system の ~1618% レベル(約 56× 遅い)→ まだ大きな伸びしろあり。

2.2 C2/C3 UltraHot 専用ベンチ

固定サイズ100K iterations, workset=128

Size Baseline (UltraHot OFF) UltraHot ON 改善率 Hit Rate
16B ~40.4M ops/s ~55.0M +36.2% 🚀 ≈100%
32B ~43.5M ops/s ~50.6M +16.3% 🚀 ≈100%

Random Mixed 256B

  • Baseline: ~8.96M ops/s
  • UltraHot ON: ~8.81M ops/s-1.6%、誤差〜軽微退化)
  • 理由: C2/C3 が全体の 12% のみ → UltraHot のメリットが平均に薄まる。

結論:

  • C2/C3 UltraHot は ターゲットクラスに対しては実用級の Box
  • 他ワークロードでは「ほぼ影響なし(わずかな分岐オーバーヘッドのみ)」の範囲に収まっている。

3. Phase 15: ExternalGuard / Domain 分離の成果

3.1 以前の問題

  • free ラッパ(core/box/hak_wrappers.inc.h)が:
    • HAKMEM 所有かチェックせず、すべての free(ptr)hak_free_at(ptr, …) に投げていた。
    • その結果:
      • ベンチ内部 slotscalloc(256, sizeof(void*)) の 2KB など)も CoreAlloc に流入。
      • classify_ptr → UNKNOWN → ExternalGuard → mincore → 「解放せず leak」と判定。
    • ベンチ観測:
      • 約 0.84% の leakBenchMeta がどんどん漏れる)。
      • mincore が Tiny ベンチ CPU の ~13% を消費。

3.2 修正内容Phase 15

  • free ラッパ側:
    • 軽量なドメインチェックを追加:
      • Tiny/Pool 用の header magic を安全に読んで、HAKMEM 所有の可能性があるものだけ hak_free_at へ。
      • そうでないBenchMeta/外部)ポインタは __libc_free へ。
  • ExternalGuard:
    • UNKNOWN ポインタを「解放しないleak」方針に明示的変更。
    • デバッグ時のみ HAKMEM_EXTERNAL_GUARD_LOG=1 で原因特定用ログを出す。

3.3 結果

  • Leak 率:
    • 100K iter: 840 leaks → 0.84%
    • 500K iter: ~4200 leaks → 0.84%
    • ほぼ全部が BenchMeta / 外部ポインタであり、CoreAlloc 側の漏れではないと確認。
  • 性能:
    • 256B 固定:
      • Before: 15.9M ops/s
      • After: 16.2M ops/s+1.9%)→ domain check オーバーヘッドは軽微、むしろ微増。
  • 安定性:
    • 全サイズ128/256/512/1024Bで 500K iter 完走(クラッシュなし)。
    • ExternalGuard 経由の「危ない free」は leak に封じ込められた。

要点:
Box 境界違反BenchMeta→CoreAlloc 流入)はほぼ完全に解消。
ベンチでの mincore / ExternalGuard コストも許容範囲になった。


4. Phase 16: Dynamic Tiny/Mid Boundary A/B Testing2025-11-16完了

4.1 実装内容

ENV変数でTiny/Mid境界を動的調整可能にする機能を追加

  • HAKMEM_TINY_MAX_CLASS=7 (デフォルト): Tiny が 0-1023B を担当
  • HAKMEM_TINY_MAX_CLASS=5 (実験用): Tiny が 0-255B のみ担当

実装ファイル:

  • hakmem_tiny.h/c: tiny_get_max_size() - ENV読取とクラス→サイズマッピング
  • hakmem_mid_mt.h/c: mid_get_min_size() - 動的境界調整(サイズギャップ防止)
  • hak_alloc_api.inc.h: 静的TINY_MAX_SIZEを動的呼び出しに変更

4.2 A/B Benchmark Results

Size Config A (C0-C7) Config B (C0-C5) 変化率
128B 6.34M ops/s 1.38M ops/s -78%
256B 6.34M ops/s 1.36M ops/s -79%
512B 5.55M ops/s 1.33M ops/s -76%
1024B 5.91M ops/s 1.37M ops/s -77%

4.3 発見と結論

成功: サイズギャップ修正完了OOMクラッシュなし 失敗: Tiny カバレッジ削減で大幅な性能劣化 (-76% ~ -79%) ⚠️ 根本原因: Mid の粗いサイズクラス (8KB/16KB/32KB) が小サイズで非効率

  • Mid は 8KB ページ単位の設計 → 256B-1KB を投げると 8KB ページをほぼ数ブロックのために確保
  • ページ fault・TLB・メタデータコストが相対的に巨大
  • Tiny は slab + freelist で高密度 → 同じサイズでも桁違いに効率的

教訓ChatGPT先生分析:

  1. Mid 箱の前提が「8KB〜用」になっている
    • 256B/512B/1024B では 8KB ページをほぼ1〜数個のブロックのために確保 → 非効率
  2. パス長も Mid の方が長いPoolTLS / mid registry / page 管理)
  3. 「Tiny を削って Mid に任せれば軽くなる」という仮説は、現行の "8KB〜前提の Mid 設計" では成り立たない

推奨: デフォルト HAKMEM_TINY_MAX_CLASS=7 (C0-C7) を維持


5. Phase 17: Small-Mid Allocator Box - 実験完了 2025-11-16

5.1 目標と動機

問題: Tiny C5-C7 (256B/512B/1KB) が ~6M ops/s → system malloc の ~6.7% レベル 仮説: 専用層を作れば 2-4x 改善可能 結果: 仮説は誤り - 性能改善なし±0-1%

5.2 Phase 17-1: TLS Frontend CacheTiny delegation

実装:

  • TLS freelist256B/512B/1KB、容量32/24/16
  • Backend: Tiny C5/C6/C7に委譲、Header変換0xa0 → 0xb0
  • Auto-adjust: Small-Mid ON時にTinyをC0-C5に自動制限

結果:

Size OFF ON 変化率
256B 5.87M 6.06M +3.3%
512B 6.02M 5.91M -1.9%
1024B 5.58M 5.54M -0.6%
平均 5.82M 5.84M +0.3%

教訓: Delegation overhead = TLS savings → 正味利益ゼロ

5.3 Phase 17-2: Dedicated SuperSlab Backend

実装:

  • Small-Mid専用SuperSlab pool1MB、16 slabs/SS
  • Batch refill8-16 blocks/refill
  • 直接0xb0 header書き込みTiny delegationなし

結果:

Size OFF ON 変化率
256B 6.08M 5.84M -4.1% ⚠️
512B 5.79M 5.86M +1.2%
1024B 5.42M 5.44M +0.4%
平均 5.76M 5.71M -0.9%

Phase 17-1比較: Phase 17-2の方が悪化-3.6% on 256B

5.4 根本原因分析ChatGPT先生 + perf profiling

発見: 70% page fault が支配的 🔥

Perf分析:

  • asm_exc_page_fault: 70% CPU時間
  • 実際のallocation logicTLS/refill: 30% のみ
  • 結論: Frontend実装は成功、Backendが重すぎる

なぜpage faultが多いか:

Small-Mid: alloc → TLS miss → refill → SuperSlab新規確保
  → mmap(1MB) → page fault 発生 → 70%のCPU消費

Tiny: alloc → TLS miss → refill → 既存warm SuperSlab使用
  → page faultなし → 高速

Small-Mid問題:

  1. 新しいSuperSlabを頻繁に確保workloadが短いため
  2. Warm SuperSlabの再利用なしusedカウンタ減らない
  3. Batch refillのメリットよりmmap/page faultコストが大きい

5.5 Phase 17の結論と教訓

Small-Mid専用層戦略は失敗:

  • Phase 17-1Frontend only: +0.3%
  • Phase 17-2Dedicated backend: -0.9%
  • 目標2-4x改善: 未達成-50-67%不足)

重要な発見:

  1. FrontendTLS/batch refill設計はOK - 30%のみの負荷
  2. 70% page fault = SuperSlab層の問題
  3. Tiny (6.08M) は既に十分速い - これを超えるのは困難
  4. 層の分離では性能は上がらない - Backend最適化が必要

実装の価値:

  • ENV=0でゼロオーバーヘッドbranch predictor学習
  • 実験記録として価値あり("なぜ専用層が効果なかったか"の証拠)
  • Tiny最適化の邪魔にならない完全分離アーキテクチャ

5.6 次のステップ: SuperSlab ReusePhase 18候補

ChatGPT提案: Tiny SuperSlabの最適化Small-Mid専用層ではなく

Box SS-ReuseSuperSlab slab再利用箱:

  • 目標: 70% page fault → 5-10%に削減
  • 戦略:
    1. meta->freelistを優先使用現在はbump onlyで再利用なし
    2. slabがemptyになったらshared_poolに返却
    3. 同じSuperSlab内で長く回す新規mmap削減
  • 効果: page fault大幅削減 → 2-4x改善期待
  • 実装場所: core/hakmem_tiny_superslab.cTiny用、Small-Midではない

Box SS-Prewarm事前温め箱:

  • クラスごとにSuperSlabを事前確保Phase 11実績: +6.4%
  • page faultをbenchmark開始時に集中
  • 課題: benchmark専用、実運用では無駄

推奨: Box SS-Reuse優先実運用価値あり、根本解決


6. 未達成の目標・残課題(次フェーズ候補)

6.1 Tiny 性能ギャップSystem の ~18% 止まり)

現状:

  • System malloc が ~90M ops/s レベルのところ、
  • HAKMEM は 128〜1024B 固定で ~1516M ops/s約 18%)。

原因の切り分け(これまでの調査から):

  • FrontUltraHot/TinyHeapV2/TLS SLLのパス長はかなり短縮済み。
  • L1 dcache miss / instructions / branches は Phase 14 で大幅削減済みだが、
    • まだ Tiny が 01023B を全部抱えており、
    • 特に 512/1024B が Superslab/Pool 側のメタ負荷に効いている可能性。

候補:

  • Phase 17 で実装中! Small-Mid Box256B〜4KB 専用箱を設計し、Tiny/Mid の間を分離する。
    • 詳細は § 5. Phase 17 を参照

6.2 UltraHot/TinyHeapV2 の拡張 or 整理

  • C2/C3 UltraHot は成功16/32B 用)。
  • C4/C5 まで拡張した試みPhase 14-Bは:
    • Fixed-size では改善あり。
    • Random Mixed で shared_pool_acquire_slab() が 47.5% まで膨らみ、大退化。
    • 原因: Superslab/TLS 在庫のバランスを壊す「窃取カスケード」。

方針:

  • UltraHot は C2/C3 専用 Box に戻すC4/C5 は一旦対象外にする)。
  • もし C4/C5 を最適化したいなら、SmallMid Box の中で別設計する。

6.3 ExternalGuard の統計と自動アラート

  • 現在:
    • HAKMEM_EXTERNAL_GUARD_STATS=1 で統計を手動出力。
    • 100+ 回呼ばれたら WARNING を出すのみ。
  • 構想:
    • 「ExternalGuard 呼び出しが一定閾値を超えたら、自動で簡易レポートを吐く」Box を追加。
    • 例: Top N 呼び出し元アドレス、サイズ帯、mincore 結果 など。

7. Claude Code 君向け TODO

7.1 Phase 17: Small-Mid Allocator Box 完了2025-11-16

Phase 17-1: TLS Frontend Cache

  • 実装完了TLS freelist + Tiny delegation
  • A/B テスト: ±0.3%(性能改善なし)
  • 教訓: Delegation overhead = TLS savings

Phase 17-2: Dedicated SuperSlab Backend

  • 実装完了専用SuperSlab pool + batch refill
  • A/B テスト: -0.9%Phase 17-1より悪化
  • 根本原因: 70% page faultmmap/SuperSlab確保が重い

結論: Small-Mid専用層は性能改善なし±0-1%、Tiny最適化が必要

7.2 Phase 18 候補: SuperSlab ReuseTiny最適化

Box SS-Reuse最優先:

  1. meta->freelist優先使用現状: bump only
  2. slab empty検出→shared_pool返却
  3. 同じSuperSlab内で長く回すpage fault削減
  4. 目標: 70% page fault → 5-10%、性能 2-4x改善

Box SS-Prewarm次優先:

  1. クラスごとSuperSlab事前確保
  2. page faultをbenchmark開始時に集中
  3. Phase 11実績: +6.4%(参考値)

Box SS-HotHint長期:

  1. クラス別ホットSuperSlab管理
  2. locality最適化cache効率
  3. SS-Reuseとの統合

7.3 その他タスク

  1. Phase 16/17 結果分析 - CURRENT_TASK.md記録完了
  2. C2/C3 UltraHot コード掃除 - C4/C5関連を別Box化
  3. ExternalGuard 統計自動化 - 閾値超過時レポート

8. Phase 17 実装ログ(完了)

2025-11-16

  • Phase 17-1完了: TLS Frontend + Tiny delegation

    • 実装: hakmem_smallmid.h/c, auto-adjust, routing修正
    • A/B結果: +0.3%(性能改善なし)
    • 教訓: Delegation overhead = TLS savings
  • Phase 17-2完了: Dedicated SuperSlab backend

    • 実装: hakmem_smallmid_superslab.h/c, batch refill, 0xb0 header
    • A/B結果: -0.9%Phase 17-1より悪化
    • 根本原因: 70% page faultChatGPT + perf分析
  • 重要な発見:

    • FrontendTLS/batch refill: OK30%のみ)
    • BackendSuperSlab確保: ボトルネック70% page fault
    • 専用層では性能上がらない → Tiny SuperSlab最適化が必要
  • CURRENT_TASK.md更新: Phase 17結果 + Phase 18計画

  • 🎯 : Phase 18 Box SS-Reuse実装Tiny SuperSlab最適化


9. Phase 19 実装ログ(完了) 🎉

2025-11-16

  • Phase 19-1完了: Box FrontMetrics観測

    • 実装: core/box/front_metrics_box.h/c、全層にヒット率計測追加
    • ENV: HAKMEM_TINY_FRONT_METRICS=1, HAKMEM_TINY_FRONT_DUMP=1
    • 結果: CSV形式で per-class ヒット率レポート生成
  • Phase 19-2完了: ベンチマークとヒット率分析

    • ワークロード: Random Mixed 16-1040B、50万イテレーション
    • 重要な発見:
      • HeapV2: 88-99% ヒット率(主力として機能)
      • UltraHot: 0.2-11.7% ヒット率(ほぼ素通り)⚠️
      • FC/SFC: 無効化済み0%
      • TLS SLL: fallback として 0.7-2.7% のみ
  • Phase 19-3完了: Box FrontPrune診断

    • 実装: ENV切り替えで層を個別ON/OFF可能
    • ENV: HAKMEM_TINY_FRONT_ENABLE_ULTRAHOT=1デフォルトOFF
    • ENV: HAKMEM_TINY_FRONT_DISABLE_HEAPV2=1デフォルトON
  • Phase 19-4完了: A/Bテストと最適化

    • テスト結果:

      設定 性能 vs Baseline C2/C3 ヒット率
      Baseline両方ON 10.1M ops/s - UH=11.7%, HV2=88.3%
      HeapV2のみ 11.4M ops/s +12.9% HV2=99.3%, SLL=0.7%
      UltraHotのみ 6.6M ops/s -34.4% UH=96.4% (C2), SLL=94.2% (C3)
    • 決定的結論:

      • UltraHot削除で性能向上 (+12.9%)
      • 理由: 分岐予測ミスコスト > UltraHotヒット率向上効果
      • UltraHotチェック: 88.3%のケースで無駄な分岐 → CPU分岐予測器を混乱
      • HeapV2単独の方が予測可能性が高い → 性能向上
  • デフォルト設定変更: UltraHot デフォルトOFF

    • 本番推奨: UltraHot OFF最速設定
    • 研究用: HAKMEM_TINY_FRONT_ENABLE_ULTRAHOT=1 で有効化可能
    • コードは削除せず ENV切り替えで残す研究・デバッグ用
  • Phase 19 成果:

    • ChatGPT先生の「観測→診断→治療」戦略が完璧に機能 🎓
    • 直感に反する発見UltraHotが阻害要因をデータで証明
    • A/Bテストでリスクなし確認してから最適化実施
    • 詳細: PHASE19_FRONTEND_METRICS_FINDINGS.md, PHASE19_AB_TEST_RESULTS.md

10. Phase 20 計画: Tiny ホットパス一本化 + BenchFast モード 🎯

目標

  • 性能目標: 20-30M ops/ssystem malloc の 25-35%
  • 設計目標: 「箱を崩さず」に達成(研究価値を保つ)

Phase 20-1: HeapV2 を唯一の Tiny Front に(本命ホットパス一本化)

現状認識:

  • C2/C3: HeapV2 が 88-99% を処理(本命)
  • UltraHot: 0.2-11.7% しか当たらず、分岐の邪魔(削ると +12.9%
  • FC/SFC: 実質 OFF、TLS SLL は fallback のみ

実装方針:

  1. HeapV2 を「唯一の front」として扱う:

    • C2-C5: HeapV2 → fallback だけ TLS SLL
    • 他層UltraHot, FC, SFCはホットパスから完全に外し、実験用に退避
  2. HeapV2 の中身を徹底的に薄くする:

    • size→class 再計算を全部やめて、「class_idx を渡すだけ」にする
    • 分岐を「classごとの専用関数」かテーブルジャンプにして 1-2 本に減らす
    • header 書き込み・TLS stack 操作・return までを「6-8 命令の直線」に近づける
  3. 期待効果:

    • 現在 11M ops/s → 目標 15-20M ops/s (+35-80% 改善)
    • 分岐削減 + 命令直線化 → CPU パイプライン効率向上

ENV制御:

# HeapV2専用モードPhase 20デフォルト
HAKMEM_TINY_FRONT_HEAPV2_ONLY=1  # UltraHot/FC/SFC完全バイパス

# 旧動作(研究用)
HAKMEM_TINY_FRONT_ENABLE_ULTRAHOT=1  # Phase 19設定

Phase 20-2: BenchFast モードで安全コストを外す

現状認識:

  • hak_free_at / classify_ptr / ExternalGuard / mincore など、 「LD_PRELOAD / 外部ライブラリから守る」層が、 ベンチでは「絶対に hakmem だけを使っている」前提の上に乗っている

実装方針:

  1. ベンチ用完全信頼モードBox BenchFast:

    • alloc/free ともに:
      • header 1バイト で Tiny を即判定
      • Pool/Mid/L25/ExternalGuard/registry を完全にバイパス
    • 変なポインタが来たら壊れていい(ベンチ用なので)
  2. ENV制御:

    HAKMEM_BENCH_FAST_MODE=1  # 安全コスト全外し
    
  3. 目的:

    • 「箱全部乗せ版」と「安全コスト全外し版」の差を測る
    • 「設計そのものの限界」と「安全・汎用性のコスト」の内訳を見る
    • mimalloc と同じくらい「危ないモード」で、どこまで近づけるかを研究
  4. 期待効果:

    • HeapV2専用モード: 15-20M ops/s
    • BenchFast追加: 25-30M ops/s (+65-100% vs 現状)
    • system malloc (90M ops/s) の 28-33% に到達

Phase 20-3: SuperSlab ホットセット チューニング

現状認識:

  • SS-Reuse: 再利用率 98.8%、新規 mmap 1.2% → page fault は抑えられている
  • とはいえ perf ではまだ asm_exc_page_fault がでかく見える場面もある

実装方針:

  1. Box SS-HotSet(どのクラスが何枚をホットに持つか計測):

    • クラスごとの「ホット SuperSlab 数」を 1-2 枚に抑えるように class_hints をチューニング
    • precharge (HAKMEM_TINY_SS_PRECHARGE_Cn) を使って、「最初から 2 枚だけ温める」戦略を試す
  2. Box SS-Compact(ホットセット圧縮):

    • 同じ SuperSlab に複数のホットクラスを詰め込むPhase 12 の発展)
    • 例: C2/C3 を同じ SuperSlab に配置 → キャッシュ効率向上
  3. 期待効果:

    • page fault さらに削減 → +10-20% 性能向上
    • 既存の SS-Reuse/Cache 設計を、「Tiny front が見ているサイズ帯に合わせて細かく調整」

Phase 20 実装順序

  1. Phase 20-1: HeapV2 専用モード実装(優先度: 高)

    • 期待: +35-80% (11M → 15-20M ops/s)
    • 工数: 中(既存 HeapV2 をスリム化)
  2. Phase 20-2: BenchFast モード実装(優先度: 中)

    • 期待: +65-100% (11M → 25-30M ops/s)
    • 工数: 中(安全層バイパス)
  3. Phase 20-3: SS-HotSet チューニング(優先度: 低)

    • 期待: +10-20% 追加改善
    • 工数: 小(パラメータ調整 + 計測箱追加)

Phase 20 成功条件

  • Tiny 固定サイズで 20-30M ops/s 達成system の 25-35%
  • 「箱を崩さず」達成(研究箱としての価値を保つ)
  • ENV切り替えで「安全モード」「ベンチモード」を選べる状態を維持
  • 残りの差system との 2.5-3xは「kernel/page fault + mimalloc の極端な inlining」と言える根拠を固める

Phase 20 後の展望

ここまで行けたら:

  • 「残りの差は kernel/page fault + mimalloc の極端な inlining・OS依存の差」だと自信を持って言える
  • hakmem の「研究箱」としての価値(構造をいじりやすい / 可視化しやすい)を保ったまま、 性能面でも「そこそこ実用に耐える」ラインに乗る
  • 学術論文・技術ブログでの発表材料が揃う

11. Phase 20-1 実装ログ: Box SS-HotPrewarmTLS Cache 事前確保)

2025-11-16

実装内容

  • Box SS-HotPrewarm 作成: ENV制御の per-class TLS cache prewarm

    • 実装: core/box/ss_hot_prewarm_box.h/c
    • デフォルト targets: C2/C3=128, C4/C5=64aggressive prewarm
    • ENV制御: HAKMEM_TINY_PREWARM_C2, _C3, _C4, _C5, _ALL
  • 初期化統合: hak_init_impl() から自動呼び出し

    • 384 ブロック事前確保C2=128, C3=128, C4=64, C5=64
    • box_prewarm_tls() API 使用(安全な carve-push

ベンチマーク結果500K iterations, 256B random mixed

設定 Page Faults Throughput vs Baseline
Baseline (Prewarm OFF) 10,399 15.7M ops/s -
Phase 20-1 (Prewarm ON) 10,342 16.2M ops/s +3.3%
  • Page fault 削減: 0.55%(期待: 50-66% → 現実: ほぼなし)
  • 性能向上: +3.3%15.7M → 16.2M ops/s

分析と結論

Page Fault 削減の失敗理由:

  1. ユーザーページ由来が支配的: ベンチマーク自体の初期化・データ構造確保による page fault が大半
  2. SuperSlab 事前確保の限界: 384 ブロック程度の prewarm では、ベンチマーク全体の page fault (10K+) に対して微々たる影響しかない
  3. カーネル側のコスト: asm_exc_page_fault はユーザー空間だけでは制御不可能

Cache Warming 効果:

  1. TLS SLL 事前充填: 初期の refill コスト削減
  2. CPU サイクル節約: +3.3% の性能向上
  3. 安定性向上: 初期状態が warm → 最初のアロケーションから高速

決定: 「軽い +3% 箱」として確定

  • prewarm は有効: 384 ブロック確保C2/C3=128, C4/C5=64のまま残す
  • これ以上の aggressive 化は不要: RSS 消費増 vs page fault 削減効果が見合わない
  • 次フェーズへ: BenchFast モードで「上限性能」を測定し、構造的限界を把握

変更ファイル

  • core/box/ss_hot_prewarm_box.h - NEW
  • core/box/ss_hot_prewarm_box.c - NEW
  • core/box/hak_core_init.inc.h - prewarm 呼び出し追加
  • Makefile - ss_hot_prewarm_box.o 追加

Status: Phase 20-1 完了 Phase 20-2 準備中 🎯 Next: BenchFast モード実装(安全コスト全外し → 構造的上限測定)


Phase 20-2: BenchFast Mode Implementation (2025-11-16)

Status: COMPLETE - Recursion fixed via prealloc pool + init guard Goal: Measure HAKMEM's structural performance ceiling by removing ALL safety costs Implementation: Complete (core/box/bench_fast_box.{h,c})

Design Philosophy

BenchFast mode bypasses all safety mechanisms to measure the theoretical maximum throughput:

Alloc path (6-8 instructions):

  • size → class_idx → TLS SLL pop → write header → return USER pointer
  • Bypasses: classify_ptr, Pool/Mid routing, registry, refill logic

Free path (3-5 instructions):

  • Read header → BASE pointer → TLS SLL push
  • Bypasses: registry lookup, mincore, ExternalGuard, capacity checks

Implementation Details

Files Created:

  • core/box/bench_fast_box.h - ENV-gated API with recursion guard
  • core/box/bench_fast_box.c - Ultra-minimal alloc/free + prealloc pool

Integration:

  • core/box/hak_wrappers.inc.h - malloc()/free() wrappers with BenchFast bypass
  • bench_random_mixed.c - bench_fast_init() call before benchmark loop
  • Makefile - bench_fast_box.o added to all object lists

Activation:

export HAKMEM_BENCH_FAST_MODE=1
./bench_fixed_size_hakmem 500000 256 128

Recursion Fix: Prealloc Pool Strategy

Problem: When TLS SLL is empty, bench_fast_alloc() → hak_alloc_at() → malloc() → infinite loop

Solution (User's "C案"):

  1. Prealloc pool: bench_fast_init() pre-allocates 50K blocks per class using normal path
  2. Init guard: bench_fast_init_in_progress flag prevents BenchFast during init
  3. Pop-only alloc: bench_fast_alloc() only pops from pool, NO REFILL

Key Fix (User's contribution):

// core/box/bench_fast_box.h
extern __thread int bench_fast_init_in_progress;

// core/box/hak_wrappers.inc.h (malloc wrapper)
if (__builtin_expect(!bench_fast_init_in_progress && bench_fast_enabled(), 0)) {
    return bench_fast_alloc(size);  // Only activate AFTER init complete
}

Performance Results (500K iterations, 256B fixed-size)

Mode Throughput vs Baseline vs System
Baseline (通常) 54.4M ops/s - 53.3%
BenchFast (安全コスト除去) 56.9M ops/s +4.5% 55.7%
System malloc 102.1M ops/s +87.6% 100%

🔍 Critical Discovery: Safety Costs Are NOT the Bottleneck

BenchFast で安全コストをすべて除去しても、わずか +4.5% しか改善しない!

What this reveals:

  • classify_ptr、Pool/Mid routing、registry、mincore、ExternalGuard → これらはボトルネックではない
  • 本当のボトルネックは構造的な部分
    • SuperSlab 設計1 SS = 1 class 固定)
    • メタデータアクセスパターンcache miss 多発)
    • TLS SLL 効率pointer chasing overhead
    • 877 SuperSlab 生成による巨大なメタデータフットプリント

System malloc との差:

  • Baseline: 47.7M ops/s 遅い(-46.7%
  • BenchFast でも 45.2M ops/s 遅い(-44.3%
  • → 安全コスト除去しても差は たった 2.5M ops/s しか縮まらない

Implications for Future Work

増分最適化の限界:

  • Phase 9-11 で学んだ教訓を確認:症状の緩和では埋まらない
  • 安全コストは全体の 4.5% しか占めていない
  • 残り 95.5% は構造的なボトルネック

Phase 12 Shared SuperSlab Pool の重要性:

  • 877 SuperSlab → 100-200 に削減
  • メタデータフットプリント削減 → cache miss 削減
  • 動的 slab 共有 → 使用効率向上
  • 期待性能: 70-90M ops/sSystem の 70-90%

Bottleneck Breakdown (推定)

コンポーネント CPU 時間 BenchFast で除去?
SuperSlab metadata access ~35% 構造的
TLS SLL pointer chasing ~25% 構造的
Refill + carving ~15% 構造的
classify_ptr + registry ~10% 除去済み
Pool/Mid routing ~5% 除去済み
mincore + guards ~5% 除去済み
その他 ~5% -

結論: 構造的ボトルネック75%>> 安全コスト20%

Next Steps:

  • Phase 12: Shared SuperSlab Pool本質的解決
  • 877 SuperSlab → 100-200 に削減して cache miss を大幅削減
  • 期待性能: 70-90M ops/sSystem の 70-90%

Phase 20 完了: BenchFast モードで「安全コストは 4.5%」と証明


Phase 21: Hot Path Cache Optimization (HPCO) - 構造的ボトルネック攻略 🎯

Status: 🚧 PLANNING (ChatGPT先生のフィードバック反映済み) Goal: アクセスパターン最適化で 60% CPUメタアクセス 35% + ポインタチェイス 25%)を直接攻撃 Target: 75-82M ops/sSystem malloc の 73-80%

Phase 20-2 で判明した構造的ボトルネック

BenchFast の結論:

  • 安全コストclassify_ptr/Pool routing/registry/mincore/guards= 4.5% しかない
  • 残り 45M ops/s の差 = 箱の積み方そのもの

支配的ボトルネック (60% CPU):

メタアクセス:      ~35% (SuperSlab/TinySlabMeta の複数フィールド読み書き)
ポインタチェイス:  ~25% (TLS SLL の next ポインタたどり)
carve/refill:      ~15% (batch carving + metadata updates)

1 回の alloc/free で発生すること:

  • 何段も構造体を跨ぐTLS → SuperSlab → SlabMeta → freelist
  • ポインタを何回もたどるSLL の next チェイン)
  • メタデータを何フィールドも触るused/capacity/carved/freelist/...

Phase 21 戦略ChatGPT先生フィードバック反映

Phase 21-1: Array-Based TLS Cache (C2/C3) 🔴 最優先

狙い: TLS SLL のポインタチェイス削減 → +15-20%

現状の問題:

// TLS SLL (linked list) - 3 メモリアクセス、うち 1 回は cache miss
void* ptr = g_tls_sll_head[class_idx];  // 1. ヘッド読み込み
void* next = *(void**)ptr;              // 2. next ポインタ読み込み (cache miss!)
g_tls_sll_head[class_idx] = next;       // 3. ヘッド更新

解決策: Ring Buffer:

// Box 21-1: Array-based hot cache (C2/C3 only)
typedef struct {
    void* slots[128];  // 初期サイズ 128ENV で A/B: 64/128/256
    uint16_t head;     // pop index
    uint16_t tail;     // push index
} TlsRingCache;

static __thread TlsRingCache g_hot_cache_c2;
static __thread TlsRingCache g_hot_cache_c3;

// Ultra-fast alloc (1-2 命令)
void* ptr = g_hot_cache_c2.slots[g_hot_cache_c2.head++ & 0x7F];  // ring wrap

階層化 (ChatGPT先生フィードバック):

Ring → SLL → SuperSlab
  ↑      ↑       ↑
 L0     L1      L2

- alloc: Ring → 空なら SLL → 空なら SuperSlab
- free:  Ring → 満杯なら SLL
- drain: SLL → Ring に昇格(一方向)

効果:

  • ポインタチェイス: 1 回 → 0 回
  • メモリアクセス: 3 → 2 回
  • cache locality: 配列は連続メモリ
  • 期待: +15-20% (54.4M → 62-65M ops/s)

ENV 変数:

HAKMEM_TINY_HOT_RING_C2=128   # C2 Ring サイズ (default: 128)
HAKMEM_TINY_HOT_RING_C3=128   # C3 Ring サイズ (default: 128)
HAKMEM_TINY_HOT_RING_ENABLE=1 # Ring cache 有効化

実装ポイント (ChatGPT先生):

  • Ring サイズは 64/128/256 で A/B テスト
  • C0/C1/C4/C5/C6/C7 は SLL のまま(使用頻度低い)
  • drain 時: SLL → Ring への昇格(一方向)
  • Ring が空 → SLL fallback → SuperSlab refill

Phase 21-2: Hot Slab Direct Index 🟡 中優先度

狙い: SuperSlab → slab ループ削減 → +10-15%

現状の問題:

// 毎回 32 slab をスキャン
SuperSlab* ss = g_tls_slabs[class_idx].ss;
for (int i = 0; i < 32; i++) {  // ← ループ!
    TinySlabMeta* meta = &ss->slabs[i];
    if (meta->freelist != NULL) { ... }
}

解決策: Hot Slab Cache:

// Box 21-2: Direct index to hot slab
static __thread TinySlabMeta* g_hot_slab[TINY_NUM_CLASSES];

void refill_from_hot_slab(int class_idx) {
    TinySlabMeta* hot = g_hot_slab[class_idx];

    // Hot slab が空なら更新
    if (!hot || hot->freelist == NULL) {
        hot = find_nonempty_slab(class_idx);  // 1回だけ探索
        g_hot_slab[class_idx] = hot;          // cache!
    }

    pop_batch_from_freelist(hot, ...);  // no loop!
}

効果:

  • SuperSlab → slab ループ: 削除
  • メタアクセス: 32 回 → 1 回
  • 期待: +10-15% (62-65M → 70-75M ops/s)

実装ポイント (ChatGPT先生):

  • Hot slab が EMPTY → find_nonempty_slab で差し替え
  • free 時: hot slab に返す or freelist に戻す(ポリシー決める)
  • shared_pool / SS-Reuse との整合性確保

Phase 21-3: Minimal Meta Access (C2/C3) 🟢 低優先度

狙い: 触るフィールド削減 → +5-10%

現状の問題:

// 1 alloc/free で 4-5 フィールド触る
typedef struct {
    uint16_t used;      // ✅ 必須
    uint16_t capacity;  // ❌ compile-time 定数化できる
    uint16_t carved;    // ❌ C2/C3 では使わない
    void* freelist;     // ✅ 必須
} TinySlabMeta;

解決策: アクセスパターン限定 (ChatGPT先生):

// struct を分けなくてもOK型分岐を避ける
// C2/C3 コードパスで触るのを used/freelist だけに限定

#define C2_CAPACITY 64  // compile-time 定数

static inline int c2_can_alloc(TinySlabMeta* meta) {
    return meta->used < C2_CAPACITY;  // capacity フィールド不要!
}

効果:

  • 触るフィールド: 4-5 → 2 個 (used/freelist のみ)
  • cache line 消費: 削減
  • 期待: +5-10% (70-75M → 75-82M ops/s)

実装ポイント (ChatGPT先生):

  • struct 分離は後回し(型分岐コスト vs 効果のトレードオフ)
  • アクセスパターン限定だけでも cache 効果あり
  • Phase 21-1/2 の結果を見てから判断

Phase 21 実装順序

Phase 21-1 (Array-based TLS Cache C2/C3):
  ↓ +15-20% → 62-65M ops/s
Phase 21-2 (Hot Slab Direct Index):
  ↓ +10-15% → 70-75M ops/s
Phase 21-3 (Minimal Meta Access):
  ↓ +5-10%  → 75-82M ops/s
  ↓
🎯 Target: System malloc の 73-80%

Phase 12 (SuperSlab 共有) は後回し:

  • Phase 21 で 80M ops/s 到達後、残り 20M ops/s を Phase 12 で詰める

ChatGPT先生フィードバック重要

  1. Box 21-1 (Ring cache): perf 的にドンピシャ

    • Ring → SLL → SuperSlab の階層を明確に
    • Ring サイズは 128/64 から ENV で A/B
    • drain 時: SLL → Ring への昇格(一方向)
  2. Box 21-2 (Hot slab): 有効だが扱いに注意

    • hot slab が EMPTY 時の差し替えロジック
    • shared_pool / SS-Reuse との整合性
  3. Box 21-3 (Minimal meta): ⚠️ 後回しでOK

    • struct 分離は型分岐コスト増
    • アクセスパターン限定だけで効果あり
    • 21-1/2 の結果を見てから判断
  4. Phase 12 との順番: 合理的

    • アクセスパターン > SuperSlab 数
    • Phase 21 → Phase 12 の順で問題なし

実装リスク

低リスク:

  • C2/C3 のみ変更(他クラスは SLL のまま)
  • 既存構造を大きく変えない
  • ENV で A/B テスト可能

注意点:

  • Ring と SLL の境界を明確に
  • shared_pool / SS-Reuse との整合
  • 型分岐が増えすぎないように

次のアクション

Phase 21-1 実装開始:

  1. core/box/hot_ring_cache_box.{h,c} 作成
  2. C2/C3 専用 TlsRingCache 実装
  3. Ring → SLL → SuperSlab 階層化
  4. ENV: HAKMEM_TINY_HOT_RING_ENABLE=1
  5. ベンチマーク: 目標 62-65M ops/s (+15-20%)


HAKMEM ハング問題調査 (2025-11-16)

症状

  1. bench_fixed_size_hakmem 1 16 128 → 5秒以上ハング
  2. bench_random_mixed_hakmem 500000 256 42 → キルされた

Root Cause

Cross-thread check の always-on 化 (直前の修正)

  • core/tiny_free_fast_v2.inc.h:175-204 で ENV ゲート削除
  • Single-thread でも毎回 SuperSlab lookup 実行

ハング箇所の推定 (確度順)

箇所 ファイル:行 原因 確度
hak_super_lookup() registry probing core/hakmem_super_registry.h:119-187 線形探索 32-64 iterations / free
Node pool exhausted fallback core/hakmem_shared_pool.c:394-400 sp_freelist_push_lockfree fallback の unsafe
tls_sll_push() CAS loop core/box/tls_sll_box.h:75-184 単純実装、無限ループはなさそう

パフォーマンス影響

Before (header-based):  5-10 cycles/free
After (cross-thread):  110-520 cycles/free (11-51倍遅い)

500K iterations:
  500K × 200 cycles = 100M cycles @ 3GHz = 33ms
  → Overhead は大きいが単なる遅さ?

Node pool exhausted の真実

  • MAX_FREE_NODES_PER_CLASS = 4096
  • 500K iterations > 4096 → exhausted ⚠️
  • しかし fallback (sp_freelist_push()) は lock-free で安全
  • 副作用であり、直接的ハング原因ではない可能性高い

推奨修正

ENV ゲートで cross-thread check を復活

// core/tiny_free_fast_v2.inc.h:175
static int g_larson_fix = -1;
if (__builtin_expect(g_larson_fix == -1, 0)) {
    const char* e = getenv("HAKMEM_TINY_LARSON_FIX");
    g_larson_fix = (e && *e && *e != '0') ? 1 : 0;
}

if (__builtin_expect(g_larson_fix, 0)) {
    // Cross-thread check - only for MT
    SuperSlab* ss = hak_super_lookup(base);
    // ... rest of check
}

利点:

  • Single-thread ベンチ: 5-10 cycles (fast)
  • Larson MT: HAKMEM_TINY_LARSON_FIX=1 で有効 (safe)

検証コマンド

# 1. ハング確認
timeout 5 ./out/release/bench_fixed_size_hakmem 1 16 128
echo $?  # 124 = timeout

# 2. 修正後確認
HAKMEM_TINY_LARSON_FIX=0 ./out/release/bench_fixed_size_hakmem 1 16 128
# Should complete fast

# 3. 500K テスト
./out/release/bench_random_mixed_hakmem 500000 256 42 2>&1 | grep "Node pool"
# Output: [P0-4 WARN] Node pool exhausted for class 7

詳細レポート

  • HANG分析: /tmp/HAKMEM_HANG_INVESTIGATION_FINAL.md