// hakmem_env_cache.h - ENV Variable Cache Box (Phase Priority-2 Refactoring) // 箱理論: ENV Caching Layer - Parse all ENV variables once at startup // // Purpose: Eliminate ~2000 syscalls/second from hot malloc/free paths // Problem: getenv() in hot path causes kernel trap (>100 cycles per call) // Solution: Parse all ENV variables at process start, cache in TLS/globals // // Architecture: // - Single init entry point: hakmem_env_cache_init() (called from hakmem_init) // - All ENV variables parsed once, cached in static storage // - Hot path code uses cached values (1-2 cycle lookup vs 100+ cycle syscall) // // Design: Box Pattern (stateless inline header with single responsibility) #ifndef HAKMEM_ENV_CACHE_H #define HAKMEM_ENV_CACHE_H #include // getenv() #include // fprintf, stderr #include // strcmp() // ============================================================================ // ENV Cache Structure // ============================================================================ // Global ENV cache (parsed once at init, read-only thereafter) typedef struct { // ===== Hot Path: Tiny Alloc Fast (7 variables) ===== int tiny_active_track; // HAKMEM_TINY_ACTIVE_TRACK (default: 0) int tiny_alloc_1024_metric; // HAKMEM_TINY_ALLOC_1024_METRIC (default: 0) int tiny_profile; // HAKMEM_TINY_PROFILE (default: 0) int tiny_heap_v2_stats; // HAKMEM_TINY_HEAP_V2_STATS (default: 0) int tiny_front_slim; // HAKMEM_TINY_FRONT_SLIM (default: 0) int sfc_cascade_pct; // HAKMEM_SFC_CASCADE_PCT (default: 50) int tiny_sfc_cascade; // HAKMEM_TINY_SFC_CASCADE (default: 0) // ===== Hot Path: Tiny Free Fast (3 variables) ===== int tiny_no_class_map; // HAKMEM_TINY_NO_CLASS_MAP (default: 0) int tiny_larson_fix; // HAKMEM_TINY_LARSON_FIX (default: 0) // ===== Hot Path: SuperSlab Alloc (1 variable) ===== int tiny_alloc_remote_relax; // HAKMEM_TINY_ALLOC_REMOTE_RELAX (default: 0) // ===== Hot Path: SuperSlab Free (5 variables) ===== int tiny_sll_diag; // HAKMEM_TINY_SLL_DIAG (default: 0) int tiny_route_free; // HAKMEM_TINY_ROUTE_FREE (default: 0) int tiny_free_to_ss; // HAKMEM_TINY_FREE_TO_SS (default: 0) int ss_free_debug; // HAKMEM_SS_FREE_DEBUG (default: 0) // ===== Warm Path: Lazy Init (1 variable) ===== int ss_map_trace; // HAKMEM_SS_MAP_TRACE (default: 0) // ===== Warm Path: FastCache (9 variables) ===== int tiny_fast_debug; // HAKMEM_TINY_FAST_DEBUG (default: 0) int tiny_fast_debug_max; // HAKMEM_TINY_FAST_DEBUG_MAX (default: 0) int tiny_front_direct; // HAKMEM_TINY_FRONT_DIRECT (default: 0) int tiny_fast_stats; // HAKMEM_TINY_FAST_STATS (default: 0) int tiny_unified_cache; // HAKMEM_TINY_UNIFIED_CACHE (default: 1) int sfc_debug; // HAKMEM_SFC_DEBUG (default: 0) int sfc_enable; // HAKMEM_SFC_ENABLE (default: 1) int sfc_capacity; // HAKMEM_SFC_CAPACITY (default: 128) int sfc_refill_count; // HAKMEM_SFC_REFILL_COUNT (default: 16) // ===== Cold Path: Headers/Debug (12 variables) ===== int tiny_restore_header; // HAKMEM_TINY_RESTORE_HEADER (default: 0) int super_lookup_debug; // HAKMEM_SUPER_LOOKUP_DEBUG (default: 0) int quiet; // HAKMEM_QUIET (default: 0) int allow_malloc_fallback; // HAKMEM_ALLOW_MALLOC_FALLBACK (default: 1) unsigned long tiny_freelist_mask; // HAKMEM_TINY_FREELIST_MASK (default: 0) int super_reg_debug; // HAKMEM_SUPER_REG_DEBUG (default: 0) int superslab_max_cached; // HAKMEM_SUPERSLAB_MAX_CACHED (default: 8) int superslab_max_memory_mb; // HAKMEM_SUPERSLAB_MAX_MEMORY_MB (default: 256) int superslab_ttl_sec; // HAKMEM_SUPERSLAB_TTL_SEC (default: 60) int ss_lru_debug; // HAKMEM_SS_LRU_DEBUG (default: 0) int ss_prewarm_debug; // HAKMEM_SS_PREWARM_DEBUG (default: 0) int prewarm_superslabs; // HAKMEM_PREWARM_SUPERSLABS (default: 0) // ===== Warm Path: Shared Pool Acquire (5 variables) ===== int ss_empty_reuse; // HAKMEM_SS_EMPTY_REUSE (default: 1) int ss_empty_scan_limit; // HAKMEM_SS_EMPTY_SCAN_LIMIT (default: 32) int ss_acquire_debug; // HAKMEM_SS_ACQUIRE_DEBUG (default: 0) int tiny_tension_drain_enable; // HAKMEM_TINY_TENSION_DRAIN_ENABLE (default: 1) int tiny_tension_drain_threshold; // HAKMEM_TINY_TENSION_DRAIN_THRESHOLD (default: 1024) // ===== Warm Path: SmallMid (1 variable) ===== int smallmid_enable; // HAKMEM_SMALLMID_ENABLE (default: 0) // ===== Cold Path: Debug/Timing (1 variable) ===== int timing_enabled; // HAKMEM_TIMING (default: 0) // ===== Cold Path: Batch (1 variable) ===== int batch_bg; // HAKMEM_BATCH_BG (default: 0) // ===== Cold Path: Superslab Madvise (1 variable) ===== int ss_madvise_strict; // HAKMEM_SS_MADVISE_STRICT (default: 1) // ===== Pool (mid) Zero Mode (1 variable) ===== int pool_zero_mode; // HAKMEM_POOL_ZERO_MODE (default: FULL=0) } HakEnvCache; // Global cache instance (initialized once at startup) extern HakEnvCache g_hak_env_cache; // ============================================================================ // Init Function (called once at process start) // ============================================================================ static inline void hakmem_env_cache_init(void) { // Zero-init the cache (all defaults to 0) memset(&g_hak_env_cache, 0, sizeof(HakEnvCache)); // ===== Hot Path: Tiny Alloc Fast ===== { const char* e; e = getenv("HAKMEM_TINY_ACTIVE_TRACK"); g_hak_env_cache.tiny_active_track = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_ALLOC_1024_METRIC"); g_hak_env_cache.tiny_alloc_1024_metric = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_PROFILE"); g_hak_env_cache.tiny_profile = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_HEAP_V2_STATS"); g_hak_env_cache.tiny_heap_v2_stats = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_FRONT_SLIM"); g_hak_env_cache.tiny_front_slim = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SFC_CASCADE_PCT"); if (e && *e) { int v = atoi(e); if (v < 0) v = 0; if (v > 100) v = 100; g_hak_env_cache.sfc_cascade_pct = v; } else { g_hak_env_cache.sfc_cascade_pct = 50; // default: 50% } e = getenv("HAKMEM_TINY_SFC_CASCADE"); g_hak_env_cache.tiny_sfc_cascade = (e && *e && *e != '0') ? 1 : 0; } // ===== Hot Path: Tiny Free Fast ===== { const char* e; e = getenv("HAKMEM_TINY_NO_CLASS_MAP"); g_hak_env_cache.tiny_no_class_map = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_LARSON_FIX"); g_hak_env_cache.tiny_larson_fix = (e && *e && *e != '0') ? 1 : 0; } // ===== Hot Path: SuperSlab Alloc ===== { const char* e = getenv("HAKMEM_TINY_ALLOC_REMOTE_RELAX"); g_hak_env_cache.tiny_alloc_remote_relax = (e && *e && *e != '0') ? 1 : 0; } // ===== Hot Path: SuperSlab Free ===== { const char* e; e = getenv("HAKMEM_TINY_SLL_DIAG"); g_hak_env_cache.tiny_sll_diag = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_ROUTE_FREE"); g_hak_env_cache.tiny_route_free = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_FREE_TO_SS"); g_hak_env_cache.tiny_free_to_ss = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SS_FREE_DEBUG"); g_hak_env_cache.ss_free_debug = (e && *e && *e != '0') ? 1 : 0; } // ===== Warm Path: Lazy Init ===== { const char* e = getenv("HAKMEM_SS_MAP_TRACE"); g_hak_env_cache.ss_map_trace = (e && *e) ? 1 : 0; } // ===== Warm Path: FastCache ===== { const char* e; e = getenv("HAKMEM_TINY_FAST_DEBUG"); g_hak_env_cache.tiny_fast_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_FAST_DEBUG_MAX"); g_hak_env_cache.tiny_fast_debug_max = (e && *e) ? atoi(e) : 0; e = getenv("HAKMEM_TINY_FRONT_DIRECT"); g_hak_env_cache.tiny_front_direct = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_FAST_STATS"); g_hak_env_cache.tiny_fast_stats = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_UNIFIED_CACHE"); // Default: 1 (enabled), set HAKMEM_TINY_UNIFIED_CACHE=0 to disable g_hak_env_cache.tiny_unified_cache = (e && *e && *e == '0') ? 0 : 1; e = getenv("HAKMEM_SFC_DEBUG"); g_hak_env_cache.sfc_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SFC_ENABLE"); g_hak_env_cache.sfc_enable = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SFC_CAPACITY"); g_hak_env_cache.sfc_capacity = (e && *e) ? atoi(e) : 128; e = getenv("HAKMEM_SFC_REFILL_COUNT"); g_hak_env_cache.sfc_refill_count = (e && *e) ? atoi(e) : 16; } // ===== Cold Path: Headers/Debug ===== { const char* e; e = getenv("HAKMEM_TINY_RESTORE_HEADER"); g_hak_env_cache.tiny_restore_header = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SUPER_LOOKUP_DEBUG"); g_hak_env_cache.super_lookup_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_QUIET"); g_hak_env_cache.quiet = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_ALLOW_MALLOC_FALLBACK"); // Default: 1 (allow fallback), set HAKMEM_ALLOW_MALLOC_FALLBACK=0 to disable g_hak_env_cache.allow_malloc_fallback = (e && *e && *e == '0') ? 0 : 1; e = getenv("HAKMEM_TINY_FREELIST_MASK"); g_hak_env_cache.tiny_freelist_mask = (e && *e) ? strtoul(e, NULL, 16) : 0; e = getenv("HAKMEM_SUPER_REG_DEBUG"); g_hak_env_cache.super_reg_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SUPERSLAB_MAX_CACHED"); g_hak_env_cache.superslab_max_cached = (e && *e) ? atoi(e) : 8; e = getenv("HAKMEM_SUPERSLAB_MAX_MEMORY_MB"); g_hak_env_cache.superslab_max_memory_mb = (e && *e) ? atoi(e) : 256; e = getenv("HAKMEM_SUPERSLAB_TTL_SEC"); g_hak_env_cache.superslab_ttl_sec = (e && *e) ? atoi(e) : 60; e = getenv("HAKMEM_SS_LRU_DEBUG"); g_hak_env_cache.ss_lru_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_SS_PREWARM_DEBUG"); g_hak_env_cache.ss_prewarm_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_PREWARM_SUPERSLABS"); g_hak_env_cache.prewarm_superslabs = (e && *e) ? atoi(e) : 0; } // ===== Warm Path: Shared Pool Acquire ===== { const char* e; e = getenv("HAKMEM_SS_EMPTY_REUSE"); g_hak_env_cache.ss_empty_reuse = (e && *e && *e == '0') ? 0 : 1; // default: 1 (ON) e = getenv("HAKMEM_SS_EMPTY_SCAN_LIMIT"); g_hak_env_cache.ss_empty_scan_limit = (e && *e) ? atoi(e) : 32; // default: 32 e = getenv("HAKMEM_SS_ACQUIRE_DEBUG"); g_hak_env_cache.ss_acquire_debug = (e && *e && *e != '0') ? 1 : 0; e = getenv("HAKMEM_TINY_TENSION_DRAIN_ENABLE"); g_hak_env_cache.tiny_tension_drain_enable = (e == NULL || atoi(e) != 0) ? 1 : 0; // default: 1 (ON) e = getenv("HAKMEM_TINY_TENSION_DRAIN_THRESHOLD"); g_hak_env_cache.tiny_tension_drain_threshold = (e && *e) ? atoi(e) : 1024; // default: 1024 if (g_hak_env_cache.tiny_tension_drain_threshold < 64) g_hak_env_cache.tiny_tension_drain_threshold = 64; if (g_hak_env_cache.tiny_tension_drain_threshold > 65536) g_hak_env_cache.tiny_tension_drain_threshold = 65536; } // ===== Warm Path: SmallMid ===== { const char* e; e = getenv("HAKMEM_SMALLMID_ENABLE"); g_hak_env_cache.smallmid_enable = (e && atoi(e) == 1) ? 1 : 0; // default: 0 (OFF) } // ===== Cold Path: Debug/Timing ===== { const char* e; e = getenv("HAKMEM_TIMING"); g_hak_env_cache.timing_enabled = (e && strcmp(e, "1") == 0) ? 1 : 0; // default: 0 (OFF) } // ===== Cold Path: Batch ===== { const char* e; e = getenv("HAKMEM_BATCH_BG"); g_hak_env_cache.batch_bg = (e && atoi(e) != 0) ? 1 : 0; // default: 0 (OFF) } // ===== Cold Path: Superslab Madvise ===== { const char* e = getenv("HAKMEM_SS_MADVISE_STRICT"); // Default: 1 (STRICT), set HAKMEM_SS_MADVISE_STRICT=0 to relax g_hak_env_cache.ss_madvise_strict = (e && *e && *e == '0') ? 0 : 1; } // ===== Pool (mid) Zero Mode ===== { const char* e = getenv("HAKMEM_POOL_ZERO_MODE"); if (e && *e) { if (strcmp(e, "header") == 0) { g_hak_env_cache.pool_zero_mode = 1; // header-only zero } else if (strcmp(e, "off") == 0 || strcmp(e, "none") == 0 || strcmp(e, "0") == 0) { g_hak_env_cache.pool_zero_mode = 2; // zero off } else { g_hak_env_cache.pool_zero_mode = 0; // unknown -> default FULL } } else { g_hak_env_cache.pool_zero_mode = 0; // default FULL } } #if !HAKMEM_BUILD_RELEASE // Debug: Print cache summary (stderr only) if (!g_hak_env_cache.quiet) { fprintf(stderr, "[ENV_CACHE_INIT] Parsed %d ENV variables at startup\n", 50); fprintf(stderr, "[ENV_CACHE_INIT] Hot path syscalls eliminated: ~2000/sec → 0/sec\n"); fflush(stderr); } #endif } // ============================================================================ // Accessor Macros (inline, zero-cost) // ============================================================================ // Hot path accessors (use global cache, 1-2 cycle read) #define HAK_ENV_TINY_ACTIVE_TRACK() (g_hak_env_cache.tiny_active_track) #define HAK_ENV_TINY_ALLOC_1024_METRIC() (g_hak_env_cache.tiny_alloc_1024_metric) #define HAK_ENV_TINY_PROFILE() (g_hak_env_cache.tiny_profile) #define HAK_ENV_TINY_HEAP_V2_STATS() (g_hak_env_cache.tiny_heap_v2_stats) #define HAK_ENV_TINY_FRONT_SLIM() (g_hak_env_cache.tiny_front_slim) #define HAK_ENV_SFC_CASCADE_PCT() (g_hak_env_cache.sfc_cascade_pct) #define HAK_ENV_TINY_SFC_CASCADE() (g_hak_env_cache.tiny_sfc_cascade) #define HAK_ENV_TINY_NO_CLASS_MAP() (g_hak_env_cache.tiny_no_class_map) #define HAK_ENV_TINY_LARSON_FIX() (g_hak_env_cache.tiny_larson_fix) #define HAK_ENV_TINY_ALLOC_REMOTE_RELAX() (g_hak_env_cache.tiny_alloc_remote_relax) #define HAK_ENV_TINY_SLL_DIAG() (g_hak_env_cache.tiny_sll_diag) #define HAK_ENV_TINY_ROUTE_FREE() (g_hak_env_cache.tiny_route_free) #define HAK_ENV_TINY_FREE_TO_SS() (g_hak_env_cache.tiny_free_to_ss) #define HAK_ENV_SS_FREE_DEBUG() (g_hak_env_cache.ss_free_debug) // Warm path accessors #define HAK_ENV_SS_MAP_TRACE() (g_hak_env_cache.ss_map_trace) #define HAK_ENV_TINY_FAST_DEBUG() (g_hak_env_cache.tiny_fast_debug) #define HAK_ENV_TINY_FAST_DEBUG_MAX() (g_hak_env_cache.tiny_fast_debug_max) #define HAK_ENV_TINY_FRONT_DIRECT() (g_hak_env_cache.tiny_front_direct) #define HAK_ENV_TINY_FAST_STATS() (g_hak_env_cache.tiny_fast_stats) #define HAK_ENV_TINY_UNIFIED_CACHE() (g_hak_env_cache.tiny_unified_cache) #define HAK_ENV_SFC_DEBUG() (g_hak_env_cache.sfc_debug) #define HAK_ENV_SFC_ENABLE() (g_hak_env_cache.sfc_enable) #define HAK_ENV_SFC_CAPACITY() (g_hak_env_cache.sfc_capacity) #define HAK_ENV_SFC_REFILL_COUNT() (g_hak_env_cache.sfc_refill_count) // Cold path accessors #define HAK_ENV_TINY_RESTORE_HEADER() (g_hak_env_cache.tiny_restore_header) #define HAK_ENV_SUPER_LOOKUP_DEBUG() (g_hak_env_cache.super_lookup_debug) #define HAK_ENV_QUIET() (g_hak_env_cache.quiet) #define HAK_ENV_ALLOW_MALLOC_FALLBACK() (g_hak_env_cache.allow_malloc_fallback) #define HAK_ENV_TINY_FREELIST_MASK() (g_hak_env_cache.tiny_freelist_mask) #define HAK_ENV_SUPER_REG_DEBUG() (g_hak_env_cache.super_reg_debug) #define HAK_ENV_SUPERSLAB_MAX_CACHED() (g_hak_env_cache.superslab_max_cached) #define HAK_ENV_SUPERSLAB_MAX_MEMORY_MB() (g_hak_env_cache.superslab_max_memory_mb) #define HAK_ENV_SUPERSLAB_TTL_SEC() (g_hak_env_cache.superslab_ttl_sec) #define HAK_ENV_SS_LRU_DEBUG() (g_hak_env_cache.ss_lru_debug) #define HAK_ENV_SS_PREWARM_DEBUG() (g_hak_env_cache.ss_prewarm_debug) #define HAK_ENV_PREWARM_SUPERSLABS() (g_hak_env_cache.prewarm_superslabs) // Warm path: Shared Pool Acquire #define HAK_ENV_SS_EMPTY_REUSE() (g_hak_env_cache.ss_empty_reuse) #define HAK_ENV_SS_EMPTY_SCAN_LIMIT() (g_hak_env_cache.ss_empty_scan_limit) #define HAK_ENV_SS_ACQUIRE_DEBUG() (g_hak_env_cache.ss_acquire_debug) #define HAK_ENV_TINY_TENSION_DRAIN_ENABLE() (g_hak_env_cache.tiny_tension_drain_enable) #define HAK_ENV_TINY_TENSION_DRAIN_THRESHOLD() (g_hak_env_cache.tiny_tension_drain_threshold) // Warm path: SmallMid #define HAK_ENV_SMALLMID_ENABLE() (g_hak_env_cache.smallmid_enable) // Cold path: Debug/Timing #define HAK_ENV_TIMING_ENABLED() (g_hak_env_cache.timing_enabled) // Cold path: Batch #define HAK_ENV_BATCH_BG() (g_hak_env_cache.batch_bg) // Cold path: Superslab Madvise #define HAK_ENV_SS_MADVISE_STRICT() (g_hak_env_cache.ss_madvise_strict) // Pool (mid) Zero Mode #define HAK_ENV_POOL_ZERO_MODE() (g_hak_env_cache.pool_zero_mode) #endif // HAKMEM_ENV_CACHE_H