Files
hakmem/docs/archive/PHASE_6.15_P0.2_INVESTIGATION.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

6.1 KiB
Raw Blame History

Phase 6.15 P0.2 調査報告: clock_gettime 影響調査

Date: 2025-10-22 Status: 調査完了 Goal: Gemini診断clock_gettime がボトルネック)の検証


📊 Executive Summary

発見事実

  1. 軽量ベンチマーク64KB: hakmem は system malloc とほぼ同等+0.2%
  2. larsonベンチマーク8-1024B混合: 非常に遅い0.62M ops/sec
  3. ⚠️ EVOLUTION無効化: むしろ性能悪化1.05M → 0.62M、-41%

結論

  • 基本性能は正常64KB allocations で system と同等)
  • 小サイズ混合allocation で mutex オーバーヘッドが顕在化
  • clock_gettime だけが原因ではない(無効化で改善せず)

🔬 テスト結果詳細

Test 1: bench_allocators軽量、64KB固定

hakmem-baseline

$ ./bench_allocators --allocator hakmem-baseline --scenario json --iterations 10000
allocator,scenario,iterations,avg_ns,soft_pf,hard_pf,rss_kb,ops_per_sec
hakmem-baseline,json,10000,214,17,0,0,4667120

system malloc

$ ./bench_allocators --allocator system --scenario json --iterations 10000
allocator,scenario,iterations,avg_ns,soft_pf,hard_pf,rss_kb,ops_per_sec
system,json,10000,213,17,0,0,4678406

比較

Allocator 平均時間 ops/sec vs system
hakmem 214ns 4.67M +0.2%
system 213ns 4.68M baseline

結論: 64KB allocations では問題なし


Test 2: larson重量、8-1024B混合

EVOLUTION有効時修正前

# 実行: 以前のテスト結果
Throughput = 1,050,000 ops/sec (1.05M)

EVOLUTION無効時#if 0

$ cd /tmp/mimalloc-bench/bench/larson
$ env LD_PRELOAD=.../libhakmem.so ./larson 0 8 1024 10000 1 12345 1

[SiteRules] Initialized (MVP: 4-probe hash, capacity=2048)
Throughput =   623377 operations per second, relative time: 1604.167s.
[EVO] Initialized (policy=AUTO, freeze_sec=180, relearn_delta=20.00%)
Done sleeping...
[ELO] Initialized 12 strategies (thresholds: 512KB-32MB)
[Batch] Initialized (threshold=8 MB, min_size=64 KB)
[Pool] ERROR: Invalid magic in pool block!\n

比較

状態 ops/sec 実行時間 エラー
EVOLUTION有効 1.05M 不明 なし
EVOLUTION無効 0.62M 1604秒(26分) Pool ERROR

結論: EVOLUTION無効化で41%悪化 + エラー発生


🔍 原因分析

1. なぜEVOLUTION無効化で悪化したのか

仮説A: 初期化順序の問題

出力ログの順序:

[SiteRules] Initialized  ← 最初
Throughput = ...         ← ベンチマーク実行ここでallocations発生
[EVO] Initialized        ← 後から初期化!
[ELO] Initialized
[Batch] Initialized
[Pool] ERROR

問題: EVOが無効でも、hak_init() 内で各サブシステムが初期化される。しかし、EVOLUTION無効時は g_cached_strategy_id が初期化されない可能性。

仮説B: Pool ERROR との関連

[Pool] ERROR: Invalid magic in pool block!\n

該当箇所を確認する必要がある(hakmem_pool.c の error メッセージ)。


2. larson vs bench_allocators の違い

項目 larson bench_allocators
サイズ範囲 8-1024B混合 64KB固定
パターン ランダム 順次
実行時間 26分異常 <1秒
mutex競合 高頻度 低頻度

結論: 小サイズ・高頻度allocation で mutex オーバーヘッドが支配的


3. Gemini診断の評価

Gemini仮説: clock_gettime() がボトルネック1024回に1回

検証結果:

  • clock_gettime は確かに高コスト数μs
  • しかし無効化で改善せず、むしろ悪化

新たな仮説:

  • mutex lock/unlock 自体のオーバーヘッドが主因
  • 小サイズallocationsで頻度が高すぎる8-1024Bを10,000 chunks × rounds

🎯 次のステップ

Option A: EVOLUTION を元に戻す(推奨)

理由:

  • 無効化で悪化した
  • Pool ERROR が発生
  • 軽量ベンチマークでは問題なし

実装:

// hakmem.c:378
#if HAKMEM_FEATURE_EVOLUTION  // #if 0 から戻す

Option B: サンプリング頻度調整(並行実施)

現状: 1024回に1回 clock_gettime() 提案: 環境変数で制御可能に

// 環境変数: HAKMEM_EVO_SAMPLE
// 0 = disabled (default)
// 10 = 1024回に1回
// 16 = 65536回に1回

char* sample = getenv("HAKMEM_EVO_SAMPLE");
if (sample && atoi(sample) > 0) {
    int freq = atoi(sample);
    uint64_t mask = (1ULL << freq) - 1;
    if ((atomic_fetch_add(&tick_counter, 1) & mask) == 0) {
        clock_gettime(...);
    }
}

デフォルト: 0無効で最速、必要時のみ有効化


Option C: TLS 実装を優先(最終手段)

P0での性能改善を諦め、Step 3 (TLS) で根本解決。

理由:

  • 軽量ベンチマークでは既に system と同等
  • larson の遅さは mutex 競合が主因
  • TLS で 95%+ のロック回避が可能

📝 学んだこと

  1. ベンチマーク選択の重要性:

    • larson は重すぎて調査に不向き
    • 軽量ベンチマークで基本性能を先に確認すべき
  2. clock_gettime だけではない:

    • Gemini診断は部分的に正しいが、主因ではなかった
    • mutex lock/unlock の頻度が最大のボトルネック
  3. EVOLUTION の依存関係:

    • 無効化すると他の機能に影響
    • 環境変数で制御する方が安全

🚀 推奨アクション

  1. EVOLUTION を元に戻す5分
  2. 環境変数制御を実装デフォルト無効、15分
  3. 軽量ベンチマークで再テスト1分
  4. ⏭️ larson は後回しTLS実装後に再評価

Status: 調査完了、次は Option A + B 実装へ