Extract configuration, statistics, and caching boxes from pool_api.inc.h Step 1: pool_config_box.h (60 lines) - All ENV gate predicates (hak_pool_v2_enabled, hak_pool_v1_flatten_enabled, etc) - Lazy static int cache pattern (matches tiny_heap_env_box.h style) - Zero dependencies (lowest-level box) Step 2a: pool_stats_box.h (90 lines) - PoolV1FlattenStats structure with multi-phase support - pool_v1_flat_stats_dump() with phase-aware output - Destructor hook for automatic dumping on exit - Multi-phase design: supports future phases without refactoring Step 2b: pool_mid_desc_cache_box.h (60 lines) - MidDescCache structure (TLS-local single-entry LRU) - mid_desc_lookup_cached() with fast TLS hit path - Minimal external dependency: mid_desc_lookup from pool_mid_desc.inc.h Result: pool_api.inc.h reduced from 1050+ lines to ~950 lines Still contains: alloc/free implementations, helpers (next steps) Build: ✅ Clean (no warnings) Test: ✅ Benchmark passes (8.5M ops/s) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
105 lines
5.5 KiB
C
105 lines
5.5 KiB
C
// pool_stats_box.h — Box: Pool Statistics & Monitoring
|
|
//
|
|
// Purpose: Pool allocator statistics tracking for all phases
|
|
// Pattern: Atomic counters + dump on destructor
|
|
// Multi-phase design: Supports future phase extensions (POOL-MID-DN-BATCH, etc)
|
|
|
|
#ifndef POOL_STATS_BOX_H
|
|
#define POOL_STATS_BOX_H
|
|
|
|
#include "pool_config_box.h" // For hak_pool_v1_flatten_stats_enabled(), etc
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdatomic.h>
|
|
|
|
// ============================================================================
|
|
// Pool V1 Flatten Statistics
|
|
// ============================================================================
|
|
// Tracks allocation/free path hits + rejection reasons
|
|
// Multi-phase design: Each phase adds fields without disrupting others
|
|
|
|
typedef struct PoolV1FlattenStats {
|
|
// Flatten hot path stats (basic alloc/free tracking)
|
|
_Atomic uint64_t alloc_tls_hit;
|
|
_Atomic uint64_t alloc_fallback_v1;
|
|
_Atomic uint64_t free_tls_hit;
|
|
_Atomic uint64_t free_fallback_v1;
|
|
_Atomic uint64_t free_fb_page_null;
|
|
_Atomic uint64_t free_fb_not_mine;
|
|
_Atomic uint64_t free_fb_other;
|
|
|
|
// Phase POOL-FREE-V1-OPT Step 1: v2 reject reasons
|
|
_Atomic uint64_t v2_reject_total; // Total v2 free rejects (fell through to v1)
|
|
_Atomic uint64_t v2_reject_ptr_null; // ptr == NULL
|
|
|
|
// Phase POOL-FREE-V1-OPT Step 2: fast split stats
|
|
_Atomic uint64_t fastsplit_fast_hit; // Fast path taken
|
|
_Atomic uint64_t fastsplit_slow_hit; // Slow path taken (fast predicate failed)
|
|
_Atomic uint64_t v2_reject_not_init; // pool not initialized
|
|
_Atomic uint64_t v2_reject_desc_null; // mid_desc_lookup returned NULL
|
|
_Atomic uint64_t v2_reject_mf2_null; // MF2 path but mf2_addr_to_page returned NULL
|
|
} PoolV1FlattenStats;
|
|
|
|
// Global stats instance (shared by all phases)
|
|
static PoolV1FlattenStats g_pool_v1_flat_stats = {0};
|
|
|
|
// ============================================================================
|
|
// Statistics Dump & Monitoring
|
|
// ============================================================================
|
|
|
|
static inline void pool_v1_flat_stats_dump(void) {
|
|
if (!hak_pool_v1_flatten_stats_enabled() && !hak_pool_free_v1_reject_stats_enabled()) return;
|
|
|
|
if (hak_pool_v1_flatten_stats_enabled()) {
|
|
fprintf(stderr,
|
|
"[POOL_V1_FLAT] alloc_tls_hit=%llu alloc_fb=%llu free_tls_hit=%llu free_fb=%llu page_null=%llu not_mine=%llu other=%llu\n",
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.alloc_tls_hit,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.alloc_fallback_v1,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.free_tls_hit,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.free_fallback_v1,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.free_fb_page_null,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.free_fb_not_mine,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.free_fb_other,
|
|
memory_order_relaxed));
|
|
}
|
|
|
|
// Phase POOL-FREE-V1-OPT Step 1: v2 reject stats
|
|
if (hak_pool_free_v1_reject_stats_enabled()) {
|
|
fprintf(stderr,
|
|
"[POOL_V2_REJECT] total=%llu ptr_null=%llu not_init=%llu desc_null=%llu mf2_null=%llu\n",
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.v2_reject_total,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.v2_reject_ptr_null,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.v2_reject_not_init,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.v2_reject_desc_null,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.v2_reject_mf2_null,
|
|
memory_order_relaxed));
|
|
}
|
|
|
|
// Phase POOL-FREE-V1-OPT Step 2: fastsplit stats
|
|
if (hak_pool_v1_flatten_stats_enabled() && hak_pool_v1_free_fastsplit_enabled()) {
|
|
fprintf(stderr,
|
|
"[POOL_V1_FASTSPLIT] fast_hit=%llu slow_hit=%llu\n",
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.fastsplit_fast_hit,
|
|
memory_order_relaxed),
|
|
(unsigned long long)atomic_load_explicit(&g_pool_v1_flat_stats.fastsplit_slow_hit,
|
|
memory_order_relaxed));
|
|
}
|
|
}
|
|
|
|
// Dump stats on program exit (destructor attribute)
|
|
__attribute__((destructor)) static void pool_v1_flatten_stats_destructor(void) {
|
|
pool_v1_flat_stats_dump();
|
|
}
|
|
|
|
#endif // POOL_STATS_BOX_H
|