Files
hakmem/core/hakmem_debug.c
Moe Charm (CI) b741d61b46 Priority-2 ENV Cache: hakmem_debug.c (1変数追加、1箇所置換)
【追加ENV変数】
- HAKMEM_TIMING (default: 0)

【置換ファイル】
- core/hakmem_debug.c (1箇所 → ENV Cache)

【変更詳細】
1. ENV Cache (hakmem_env_cache.h):
   - 構造体に1変数追加 (47→48変数)
   - hakmem_env_cache_init()に初期化追加
   - アクセサマクロ追加
   - カウント更新: 47→48

2. hakmem_debug.c:
   - hkm_timing_init():
     getenv("HAKMEM_TIMING") + strcmp() → HAK_ENV_TIMING_ENABLED()
   - #include "hakmem_env_cache.h" 追加

【効果】
- デバッグタイミング初期化からgetenv()呼び出しを排除
- Cold pathだが、起動時のENV参照を削減

【テスト】
 make shared → 成功
 /tmp/test_mixed3_final → PASSED

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 20:56:55 +09:00

223 lines
5.6 KiB
C

// hakmem_debug.c - Debug Timing Implementation
//
// License: MIT
// Date: 2025-10-21
#include "hakmem_debug.h"
#include "hakmem_env_cache.h" // Priority-2: ENV cache
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAKMEM_DEBUG_TIMING
// ============================================================================
// Global State
// ============================================================================
static int g_timing_enabled = 0; // Runtime enable flag (set from HAKMEM_TIMING env)
static int g_initialized = 0;
// Thread-local statistics (lock-free, per-thread accumulation)
static _Thread_local HkmTimingStat g_tls_stats[HKM_CAT_MAX];
// Global statistics (accumulated from all threads at shutdown)
static HkmTimingStat g_global_stats[HKM_CAT_MAX];
// Category names for pretty printing (Phase 6.11.3: Updated for profiling)
static const char* g_category_names[HKM_CAT_MAX] = {
// Syscalls and fallbacks
"syscall_mmap",
"syscall_munmap",
"syscall_madvise",
"fallback_malloc",
// Whale Fast-Path
"whale_get",
"whale_put",
// L2.5 Pool
"l25_get",
"l25_put",
"l25_refill",
// Tiny Pool
"tiny_alloc",
"tiny_free",
"tiny_slab_search",
// BigCache
"bigcache_get",
"bigcache_put",
"bigcache_evict_scan",
// Site Rules
"site_rules_lookup",
"site_rules_adopt",
// ELO Learning
"elo_select",
"elo_update",
// Top-level API
"hak_alloc",
"hak_free",
// Legacy
"region_get",
"region_put",
"hash_fnv1a",
// Mid (L2 Pool) fine-grained
"pool_get",
"pool_lock",
"pool_refill",
"tc_drain",
"tls_fast",
"shard_steal",
// Additional Mid (L2) fine-grained (NEW)
"pool_tls_ring_pop",
"pool_tls_lifo_pop",
"pool_remote_push",
"pool_alloc_tls_page",
// L2.5 (LargePool) fine-grained (NEW)
"l25_lock",
"l25_tls_ring_pop",
"l25_tls_lifo_pop",
"l25_tc_drain",
"l25_remote_push",
"l25_alloc_tls_page",
"l25_shard_steal",
};
// ============================================================================
// Internal Helpers
// ============================================================================
static void dump_stats_internal(void) {
fprintf(stderr, "\n========================================\n");
fprintf(stderr, "HAKMEM Debug Timing Statistics\n");
fprintf(stderr, "========================================\n");
uint64_t total_cycles = 0;
for (int i = 0; i < HKM_CAT_MAX; i++) {
total_cycles += g_global_stats[i].cycles;
}
for (int i = 0; i < HKM_CAT_MAX; i++) {
HkmTimingStat* stat = &g_global_stats[i];
if (stat->count == 0) continue;
double avg_cycles = (double)stat->cycles / stat->count;
double pct = total_cycles > 0 ? (double)stat->cycles / total_cycles * 100.0 : 0.0;
fprintf(stderr, "%-24s: count=%8lu avg=%8.0f cycles total=%12lu cycles (%.1f%%)\n",
g_category_names[i],
(unsigned long)stat->count,
avg_cycles,
(unsigned long)stat->cycles,
pct);
}
fprintf(stderr, "========================================\n");
fprintf(stderr, "Total cycles: %lu\n", (unsigned long)total_cycles);
fprintf(stderr, "========================================\n");
}
static void accumulate_tls_to_global(void) {
// Accumulate thread-local stats to global (called at shutdown)
for (int i = 0; i < HKM_CAT_MAX; i++) {
g_global_stats[i].count += g_tls_stats[i].count;
g_global_stats[i].cycles += g_tls_stats[i].cycles;
}
}
static void atexit_handler(void) {
if (!g_initialized) return;
// Accumulate TLS to global
accumulate_tls_to_global();
// Dump stats
dump_stats_internal();
}
// ============================================================================
// Public API Implementation
// ============================================================================
void hkm_timing_init(void) {
if (g_initialized) return;
#if !HAKMEM_BUILD_RELEASE
// Priority-2: Use cached ENV (gated behind !HAKMEM_BUILD_RELEASE)
g_timing_enabled = HAK_ENV_TIMING_ENABLED();
#else
g_timing_enabled = 0; // Always disabled in release builds
#endif
// Initialize global stats
memset(g_global_stats, 0, sizeof(g_global_stats));
// Initialize TLS stats
memset(g_tls_stats, 0, sizeof(g_tls_stats));
// Register atexit handler
atexit(atexit_handler);
g_initialized = 1;
if (g_timing_enabled) {
fprintf(stderr, "[HAKMEM Timing] Enabled (HAKMEM_TIMING=1)\n");
}
}
void hkm_timing_shutdown(void) {
if (!g_initialized) return;
// Accumulate TLS to global
accumulate_tls_to_global();
// Dump stats
dump_stats_internal();
g_initialized = 0;
}
void hkm_count_inc(HkmTimingCategory cat) {
if (!g_timing_enabled) return;
if (cat >= HKM_CAT_MAX) return;
g_tls_stats[cat].count++;
}
void hkm_cycles_add(HkmTimingCategory cat, uint64_t cycles) {
if (!g_timing_enabled) return;
if (cat >= HKM_CAT_MAX) return;
g_tls_stats[cat].cycles += cycles;
}
void hkm_timing_dump(void) {
if (!g_initialized) return;
// Accumulate TLS to global
accumulate_tls_to_global();
// Dump stats
dump_stats_internal();
}
#else
// Build-time disabled: empty implementations
void hkm_timing_init(void) {}
void hkm_timing_shutdown(void) {}
void hkm_count_inc(HkmTimingCategory cat) { (void)cat; }
void hkm_cycles_add(HkmTimingCategory cat, uint64_t cycles) { (void)cat; (void)cycles; }
void hkm_timing_dump(void) {}
#endif