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>
6.1 KiB
6.1 KiB
Phase 6.15 P0.2 調査報告: clock_gettime 影響調査
Date: 2025-10-22 Status: ✅ 調査完了 Goal: Gemini診断(clock_gettime がボトルネック)の検証
📊 Executive Summary
発見事実
- ✅ 軽量ベンチマーク(64KB): hakmem は system malloc とほぼ同等(+0.2%)
- ❌ larsonベンチマーク(8-1024B混合): 非常に遅い(0.62M ops/sec)
- ⚠️ 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%+ のロック回避が可能
📝 学んだこと
-
ベンチマーク選択の重要性:
- larson は重すぎて調査に不向き
- 軽量ベンチマークで基本性能を先に確認すべき
-
clock_gettime だけではない:
- Gemini診断は部分的に正しいが、主因ではなかった
- mutex lock/unlock の頻度が最大のボトルネック
-
EVOLUTION の依存関係:
- 無効化すると他の機能に影響
- 環境変数で制御する方が安全
🚀 推奨アクション
- ✅ EVOLUTION を元に戻す(5分)
- ✅ 環境変数制御を実装(デフォルト無効、15分)
- ✅ 軽量ベンチマークで再テスト(1分)
- ⏭️ larson は後回し(TLS実装後に再評価)
Status: ✅ 調査完了、次は Option A + B 実装へ