Root cause: unified_cache_refill() accessed cache->slots before initialization when a size class was first used via the refill path (not pop path). Fix: Add lazy initialization check at start of unified_cache_refill() - Check if cache->slots is NULL before accessing - Call unified_cache_init() if needed - Return NULL if init fails (graceful degradation) Also includes: - ss_cold_start_box.inc.h: Box Pattern for default prewarm settings - hakmem_super_registry.c: Use static array in prewarm (avoid recursion) - Default prewarm enabled (1 SuperSlab/class, configurable via ENV) Test: 8B→16B→Mixed allocation pattern now works correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
119 lines
3.9 KiB
C
119 lines
3.9 KiB
C
// ss_cold_start_box.inc.h - SuperSlab Cold Start Protection
|
|
// ==========================================================================
|
|
//
|
|
// Purpose: Prevent OOM on cold start by enabling minimal prewarm by default
|
|
//
|
|
// Problem:
|
|
// - SuperSlab LRU cache starts empty
|
|
// - First allocation triggers mmap() which may fail
|
|
// - No prewarm by default = cold start OOM
|
|
//
|
|
// Solution (Box Pattern):
|
|
// - Default: Prewarm 1 SuperSlab per class (minimal footprint: 8MB)
|
|
// - ENV configurable: HAKMEM_SS_PREWARM_COUNT=N (0 to disable)
|
|
// - Observable: Debug logging
|
|
// - Inline: Zero runtime overhead for config access
|
|
//
|
|
// ENV Variables:
|
|
// HAKMEM_SS_PREWARM_COUNT=N - SuperSlabs per class (default: 1)
|
|
// HAKMEM_SS_PREWARM_DISABLE=1 - Disable prewarm entirely (legacy compat)
|
|
//
|
|
// Memory Impact:
|
|
// Default (count=1): 8 classes * 1MB = 8MB
|
|
// Aggressive (count=4): 8 classes * 4MB = 32MB
|
|
//
|
|
// ==========================================================================
|
|
|
|
#ifndef HAK_SS_COLD_START_BOX_INC_H
|
|
#define HAK_SS_COLD_START_BOX_INC_H
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h> // For ss_cold_start_log_config()
|
|
|
|
// ============================================================================
|
|
// Configuration Constants
|
|
// ============================================================================
|
|
|
|
// Default prewarm count per class (minimal cold start protection)
|
|
// Phase 11+: Fixed malloc() recursion by using static array in hak_ss_prewarm_class()
|
|
#define SS_COLD_START_DEFAULT_COUNT 1
|
|
|
|
// Maximum prewarm count per class (safety cap)
|
|
#define SS_COLD_START_MAX_COUNT 512
|
|
|
|
// ============================================================================
|
|
// Inline Configuration Helper
|
|
// ============================================================================
|
|
|
|
// Get cold start prewarm count (cached, ENV-configurable)
|
|
//
|
|
// Returns:
|
|
// - 0 if disabled (HAKMEM_SS_PREWARM_DISABLE=1)
|
|
// - N from HAKMEM_SS_PREWARM_COUNT=N if set
|
|
// - SS_COLD_START_DEFAULT_COUNT (1) otherwise
|
|
//
|
|
// Thread-safe: uses static cache with simple atomic semantics
|
|
//
|
|
static inline int ss_cold_start_get_count(void) {
|
|
static int g_cached = -1; // -1 = not initialized
|
|
|
|
if (__builtin_expect(g_cached >= 0, 1)) {
|
|
return g_cached; // Fast path: already cached
|
|
}
|
|
|
|
// Slow path: parse ENV
|
|
|
|
// Check disable flag first
|
|
const char* disable_env = getenv("HAKMEM_SS_PREWARM_DISABLE");
|
|
if (disable_env && *disable_env && *disable_env != '0') {
|
|
g_cached = 0; // Disabled
|
|
return 0;
|
|
}
|
|
|
|
// Check custom count
|
|
const char* count_env = getenv("HAKMEM_SS_PREWARM_COUNT");
|
|
if (count_env && *count_env) {
|
|
char* endptr;
|
|
long count = strtol(count_env, &endptr, 10);
|
|
if (*endptr == '\0' && count >= 0) {
|
|
// Cap at max
|
|
if (count > SS_COLD_START_MAX_COUNT) {
|
|
count = SS_COLD_START_MAX_COUNT;
|
|
}
|
|
g_cached = (int)count;
|
|
return g_cached;
|
|
}
|
|
// Invalid format - fall through to default
|
|
}
|
|
|
|
// Default: minimal prewarm enabled
|
|
g_cached = SS_COLD_START_DEFAULT_COUNT;
|
|
return g_cached;
|
|
}
|
|
|
|
// Check if cold start prewarm is enabled
|
|
static inline int ss_cold_start_is_enabled(void) {
|
|
return ss_cold_start_get_count() > 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Debug Helper
|
|
// ============================================================================
|
|
|
|
// Log cold start configuration (call from init for diagnostics)
|
|
static inline void ss_cold_start_log_config(void) {
|
|
#if !HAKMEM_BUILD_RELEASE
|
|
int count = ss_cold_start_get_count();
|
|
if (count > 0) {
|
|
fprintf(stderr, "[SS_COLD_START] Enabled: %d SuperSlabs per class (total: %d MB)\n",
|
|
count, count * 8); // 8 classes * 1MB
|
|
} else {
|
|
fprintf(stderr, "[SS_COLD_START] Disabled\n");
|
|
}
|
|
#else
|
|
(void)0; // No-op in release mode
|
|
#endif
|
|
}
|
|
|
|
#endif // HAK_SS_COLD_START_BOX_INC_H
|