Files
hakmem/core/hakmem_ace.c
Moe Charm (CI) 4ef0171bc0 feat: Add ACE allocation failure tracing and debug hooks
This commit introduces a comprehensive tracing mechanism for allocation failures within the Adaptive Cache Engine (ACE) component. This feature allows for precise identification of the root cause for Out-Of-Memory (OOM) issues related to ACE allocations.

Key changes include:
- **ACE Tracing Implementation**:
  - Added  environment variable to enable/disable detailed logging of allocation failures.
  - Instrumented , , and  to distinguish between "Threshold" (size class mismatch), "Exhaustion" (pool depletion), and "MapFail" (OS memory allocation failure).
- **Build System Fixes**:
  - Corrected  to ensure  is properly linked into , resolving an  error.
- **LD_PRELOAD Wrapper Adjustments**:
  - Investigated and understood the  wrapper's behavior under , particularly its interaction with  and  checks.
  - Enabled debugging flags for  environment to prevent unintended fallbacks to 's  for non-tiny allocations, allowing comprehensive testing of the  allocator.
- **Debugging & Verification**:
  - Introduced temporary verbose logging to pinpoint execution flow issues within  interception and  routing. These temporary logs have been removed.
  - Created  to facilitate testing of the tracing features.

This feature will significantly aid in diagnosing and resolving allocation-related OOM issues in  by providing clear insights into the failure pathways.
2025-12-01 16:37:59 +09:00

135 lines
5.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include "hakmem_internal.h"
#include "hakmem_config.h"
#include "hakmem_ace.h"
#include "hakmem_pool.h"
#include "hakmem_l25_pool.h"
#include "hakmem_ace_stats.h"
#include "hakmem_policy.h"
#include "hakmem_debug.h"
// Map size to MidPool/LargePool and allocate.
// Phase 6.21: Bridge classes (40KB, 52KB) now hardcoded, DYN1/DYN2 disabled
static inline size_t round_to_mid_class(size_t s, double wmax, const FrozenPolicy* pol) {
// Build candidate set: 2/4/8/16/32/40/52 KiB (Bridge classes now fixed)
size_t cand[7] = {
POOL_CLASS_2KB, POOL_CLASS_4KB, POOL_CLASS_8KB, POOL_CLASS_16KB, POOL_CLASS_32KB,
POOL_CLASS_40KB, POOL_CLASS_52KB // Phase 6.21: Bridge classes
};
// Legacy: DYN1/DYN2 support (currently disabled in Phase 6.21)
// Note: If DYN classes are re-enabled, they should override Bridge classes
if (pol) {
if (pol->mid_dyn1_bytes >= POOL_MIN_SIZE && pol->mid_dyn1_bytes <= POOL_MAX_SIZE) cand[5] = (size_t)pol->mid_dyn1_bytes;
if (pol->mid_dyn2_bytes >= POOL_MIN_SIZE && pol->mid_dyn2_bytes <= POOL_MAX_SIZE) cand[6] = (size_t)pol->mid_dyn2_bytes;
}
// Choose the smallest c >= s that also satisfies c ≤ wmax*s
size_t best = 0; // 0 = not found
for (int i = 0; i < 7; i++) {
size_t c = cand[i];
if (c == 0) continue;
if (c < s) continue;
if ((double)c > wmax * (double)s) continue;
if (best == 0 || c < best) best = c;
}
return best;
}
static inline size_t round_to_large_class(size_t s, double wmax) {
const size_t classes[L25_NUM_CLASSES] = {
L25_CLASS_64KB, L25_CLASS_128KB, L25_CLASS_256KB, L25_CLASS_512KB, L25_CLASS_1MB
};
for (int i = 0; i < L25_NUM_CLASSES; i++) {
size_t c = classes[i];
if (s <= c) {
if ((double)c <= wmax * (double)s) return c;
return 0; // not allowed → fallback
}
}
return 0; // above 1MB
}
void* hkm_ace_alloc(size_t size, uintptr_t site_id, const FrozenPolicy* pol) {
double wmax_mid = (pol ? pol->w_max_mid : 1.33);
double wmax_large = (pol ? pol->w_max_large : 1.25);
// MidPool: 252KiB (Phase 6.21: with Bridge classes for W_MAX rounding)
if (size >= 33000 && size <= 34000) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[ACE] Processing 33KB: size=%zu, POOL_MAX_SIZE=%d\n", size, POOL_MAX_SIZE);
#endif
}
if (size <= POOL_MAX_SIZE) {
size_t r = round_to_mid_class(size, wmax_mid, pol);
if (size >= 33000 && size <= 34000) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[ACE] round_to_mid_class returned: %zu (0 means no valid class)\n", r);
#endif
}
if (r != 0) {
// Debug: Log 33KB allocation routing (only in debug builds)
#ifdef HAKMEM_DEBUG_VERBOSE
if (size >= 33000 && size <= 34000) {
HAKMEM_LOG("[ACE] 33KB alloc: size=%zu → rounded=%zu (class 5: 40KB)\n", size, r);
}
#endif
if (size >= 33000 && size <= 34000) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr, "[ACE] Calling hak_pool_try_alloc with size=%zu\n", r);
#endif
}
HKM_TIME_START(t_mid_get);
void* p = hak_pool_try_alloc(r, site_id);
HKM_TIME_END(HKM_CAT_POOL_GET, t_mid_get);
hkm_ace_stat_mid_attempt(p != NULL);
if (p) return p;
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Exhaustion: size=%zu class=%zu (MidPool)\n", size, r);
}
} else {
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Threshold: size=%zu wmax=%.2f (MidPool)\n", size, wmax_mid);
}
}
// If rounding not allowed or miss, fallthrough to large class rounding below
}
// LargePool: 64KiB1MiB (with W_MAX rounding)
if (size <= L25_MAX_SIZE) {
size_t r = round_to_large_class(size, wmax_large);
if (r != 0) {
HKM_TIME_START(t_l25_get);
void* p = hak_l25_pool_try_alloc(r, site_id);
HKM_TIME_END(HKM_CAT_L25_GET, t_l25_get);
hkm_ace_stat_large_attempt(p != NULL);
if (p) return p;
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Exhaustion: size=%zu class=%zu (LargePool)\n", size, r);
}
} else {
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Threshold: size=%zu wmax=%.2f (LargePool)\n", size, wmax_large);
}
}
} else if (size > POOL_MAX_SIZE && size < L25_MIN_SIZE) {
// Gap 3264KiB: try rounding up to 64KiB if permitted
// size_t r = round_to_large_class(L25_MIN_SIZE, wmax_large); // check 64KiB vs size (unused)
if ((double)L25_MIN_SIZE <= wmax_large * (double)size) {
HKM_TIME_START(t_l25_get2);
void* p = hak_l25_pool_try_alloc(L25_MIN_SIZE, site_id);
HKM_TIME_END(HKM_CAT_L25_GET, t_l25_get2);
hkm_ace_stat_large_attempt(p != NULL);
if (p) return p;
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Exhaustion: size=%zu class=64KB (Gap)\n", size);
}
} else {
if (g_hakem_config.ace_trace) {
fprintf(stderr, "[ACE-FAIL] Threshold: size=%zu wmax=%.2f (Gap)\n", size, wmax_large);
}
}
}
hkm_ace_stat_l1_fallback();
return NULL; // Miss: let caller fallback to malloc
}