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.9 KiB
6.9 KiB
Phase 6.15 P0.3 完了報告: EVOLUTION復元 + 環境変数制御
Date: 2025-10-22 Status: ✅ 完了 Goal: EVOLUTION復元 + 環境変数制御実装(デフォルト無効)
📊 Executive Summary
実装完了内容
✅ EVOLUTION block 復元: #if 0 → #if HAKMEM_FEATURE_EVOLUTION
✅ 環境変数制御追加: HAKMEM_EVO_SAMPLE(デフォルト=0で無効)
✅ 性能検証完了: system malloc とほぼ同等(+1.0%)
🔧 実装詳細
1. グローバル変数追加 (hakmem.c:61-62)
// Phase 6.15 P0.3: EVO Sampling Control (environment variable)
static uint64_t g_evo_sample_mask = 0; // 0 = disabled (default), (1<<N)-1 = sample every 2^N calls
目的: サンプリング頻度を環境変数で制御
2. 環境変数読み込み (hakmem.c:283-300)
// Phase 6.15 P0.3: Configure EVO sampling from environment variable
// HAKMEM_EVO_SAMPLE: 0=disabled (default), N=sample every 2^N calls
// Example: HAKMEM_EVO_SAMPLE=10 → sample every 1024 calls
// HAKMEM_EVO_SAMPLE=16 → sample every 65536 calls
char* evo_sample_str = getenv("HAKMEM_EVO_SAMPLE");
if (evo_sample_str && atoi(evo_sample_str) > 0) {
int freq = atoi(evo_sample_str);
if (freq >= 64) {
fprintf(stderr, "[hakmem] Warning: HAKMEM_EVO_SAMPLE=%d too large, using 63\n", freq);
freq = 63;
}
g_evo_sample_mask = (1ULL << freq) - 1;
HAKMEM_LOG("EVO sampling enabled: every 2^%d = %llu calls\n",
freq, (unsigned long long)(g_evo_sample_mask + 1));
} else {
g_evo_sample_mask = 0; // Disabled by default
HAKMEM_LOG("EVO sampling disabled (HAKMEM_EVO_SAMPLE not set or 0)\n");
}
機能:
- 環境変数未設定 →
g_evo_sample_mask = 0(無効、最速) HAKMEM_EVO_SAMPLE=10→ 1024回に1回サンプリングHAKMEM_EVO_SAMPLE=16→ 65536回に1回サンプリング(極軽量)- 上限64(オーバーフロー防止)
3. EVOLUTION Block 復元 (hakmem.c:400-417)
Before (P0.2):
#if 0 // HAKMEM_FEATURE_EVOLUTION ← 無効化(性能悪化の原因)
static _Atomic uint64_t tick_counter = 0;
if ((atomic_fetch_add(&tick_counter, 1) & 0x3FF) == 0) {
clock_gettime(...);
}
#endif
After (P0.3):
#if HAKMEM_FEATURE_EVOLUTION ← 復元
// Only sample if enabled via HAKMEM_EVO_SAMPLE environment variable
if (g_evo_sample_mask > 0) { ← 環境変数で制御
static _Atomic uint64_t tick_counter = 0;
if ((atomic_fetch_add(&tick_counter, 1) & g_evo_sample_mask) == 0) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint64_t now_ns = now.tv_sec * 1000000000ULL + now.tv_nsec;
if (hak_evo_tick(now_ns)) {
int new_strategy = hak_elo_select_strategy();
atomic_store(&g_cached_strategy_id, new_strategy);
}
}
}
#endif
重要な変更:
if (g_evo_sample_mask > 0)チェック追加 → デフォルトで完全に無効化& g_evo_sample_mask→ 固定値0x3FFから動的マスクへ変更
📊 ベンチマーク結果
Test 1: デフォルト(EVOLUTION無効)
./bench_allocators --allocator hakmem-baseline --scenario json --iterations 10000
結果:
hakmem-baseline,json,10000,210,17,0,0,4758892
- 平均時間: 210ns/op
- Throughput: 4.76M ops/sec
Test 2: system malloc(比較)
./bench_allocators --allocator system --scenario json --iterations 10000
結果:
system,json,10000,208,17,0,0,4802216
- 平均時間: 208ns/op
- Throughput: 4.80M ops/sec
Test 3: EVOLUTION有効(1024サンプリング)
HAKMEM_EVO_SAMPLE=10 ./bench_allocators --allocator hakmem-baseline --scenario json --iterations 10000
結果:
hakmem-baseline,json,10000,215,17,0,0,4639566
- 平均時間: 215ns/op
- Throughput: 4.64M ops/sec
比較表
| モード | 平均時間 | ops/sec | vs system | 備考 |
|---|---|---|---|---|
| hakmem (default, EVO無効) | 210ns | 4.76M | +1.0% | ✅ 最速 |
| system malloc | 208ns | 4.80M | baseline | 比較基準 |
| hakmem (EVO有効, 1024) | 215ns | 4.64M | +3.4% | 学習ON時 |
✅ 検証項目
- ✅ EVOLUTION復元成功:
#if 0→#if HAKMEM_FEATURE_EVOLUTION - ✅ 環境変数制御動作:
HAKMEM_EVO_SAMPLE正常動作 - ✅ デフォルト無効: 環境変数未設定で
g_evo_sample_mask = 0 - ✅ 性能維持: system malloc と +1.0% (ほぼ同等)
- ✅ サンプリングON時オーバーヘッド: +2.4% (210ns → 215ns) 許容範囲
🎯 次のステップ
Option A: larson ベンチマークで再テスト(推奨しない)
理由:
- larson は重すぎて調査に不向き(26分実行)
- 小サイズ混合allocation で mutex オーバーヘッドが支配的
- TLS実装(Step 3)まで待つべき
Option B: Step 3へ進む(推奨)
次フェーズ: Phase 6.15 Step 3 (TLS Multi-threaded)
目標:
- Thread-Local Storage (TLS) 実装
- Tiny Pool / L2 Pool / L2.5 Pool を TLS化
- 95%+ のロック回避 → 13-15M ops/sec on larson (4T)
見積もり: 8-10時間
根拠:
- Phase 6.13 で TLS validation 済み (+123-146% 実証済み)
- 軽量ベンチマークは既に system と同等
- TLS なしでは larson の性能改善は不可能
📝 学んだこと
1. EVOLUTION無効化は逆効果だった
P0.2の結果:
- EVOLUTION無効化 → 性能41%悪化(1.05M → 0.62M)
- Pool ERROR 発生
- 初期化依存関係の複雑さ
教訓: 部分的無効化より、環境変数で完全制御する方が安全
2. デフォルト無効 + opt-in が最適
設計:
- デフォルト:
g_evo_sample_mask = 0(無効、最速) - 必要時のみ:
HAKMEM_EVO_SAMPLE=10(学習ON)
利点:
- ✅ 初期性能: system と同等
- ✅ 学習機能: オプトイン可能
- ✅ デバッグ: 環境変数で簡単に切り替え
3. 軽量ベンチマークの重要性
larson vs bench_allocators:
| 項目 | larson | bench_allocators |
|---|---|---|
| 実行時間 | 26分 | <1秒 |
| サイズ範囲 | 8-1024B混合 | 64KB固定 |
| デバッグ向き | ❌ | ✅ |
教訓: 基本性能確認は軽量ベンチマークで、本番想定は重量ベンチマークで
🚀 推奨アクション
- ✅ P0.3 完了確認 - このドキュメント作成
- ⏭️ CURRENT_TASK.md 更新 - 次のステップ記録
- ⏭️ Step 3 計画立案 - TLS実装詳細設計
- ⏭️ ultrathink 起動 - TLS実装計画作成
Status: ✅ P0.3 完了、次は Step 3(TLS実装)へ