Phase POOL-MID-DN-BATCH Step 3: Statistics counters for deferred inuse_dec

This commit is contained in:
Moe Charm (CI)
2025-12-12 22:59:56 +09:00
parent b381515b16
commit d45729f063

View File

@ -0,0 +1,69 @@
// pool_mid_inuse_deferred_stats_box.h — Box: Deferred inuse_dec Statistics
//
// Purpose: Track deferred inuse_dec performance counters
// Pattern: Atomic counters with destructor dump
// Phase: POOL-MID-DN-BATCH Step 5
//
// Counters:
// - mid_inuse_deferred_hit: Total deferred decrements (hot path)
// - drain_calls: Number of drain operations (cold path)
// - pages_drained: Total pages processed in drain
// - empty_transitions: Pages that triggered DONTNEED
#ifndef POOL_MID_INUSE_DEFERRED_STATS_BOX_H
#define POOL_MID_INUSE_DEFERRED_STATS_BOX_H
#include <stdint.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
// Statistics structure
typedef struct {
_Atomic uint64_t mid_inuse_deferred_hit; // Total deferred decrements
_Atomic uint64_t drain_calls; // Number of drain calls
_Atomic uint64_t pages_drained; // Total pages drained
_Atomic uint64_t empty_transitions; // Pages that went to 0
} MidInuseDeferredStats;
// Global stats instance
static MidInuseDeferredStats g_mid_inuse_deferred_stats;
// Stats increment macros (inline for hot path)
#define MID_INUSE_DEFERRED_STAT_INC(field) \
atomic_fetch_add_explicit(&g_mid_inuse_deferred_stats.field, 1, memory_order_relaxed)
#define MID_INUSE_DEFERRED_STAT_ADD(field, n) \
atomic_fetch_add_explicit(&g_mid_inuse_deferred_stats.field, (n), memory_order_relaxed)
// Dump stats on exit (if ENV var set)
static void mid_inuse_deferred_stats_dump(void) {
// Only dump if deferred is enabled
const char* e = getenv("HAKMEM_POOL_MID_INUSE_DEFERRED");
if (!e || *e != '1') return;
uint64_t hits = atomic_load_explicit(&g_mid_inuse_deferred_stats.mid_inuse_deferred_hit, memory_order_relaxed);
uint64_t drains = atomic_load_explicit(&g_mid_inuse_deferred_stats.drain_calls, memory_order_relaxed);
uint64_t pages = atomic_load_explicit(&g_mid_inuse_deferred_stats.pages_drained, memory_order_relaxed);
uint64_t empties = atomic_load_explicit(&g_mid_inuse_deferred_stats.empty_transitions, memory_order_relaxed);
if (hits > 0 || drains > 0) {
fprintf(stderr, "\n=== Mid Inuse Deferred Stats ===\n");
fprintf(stderr, "Deferred hits: %lu\n", hits);
fprintf(stderr, "Drain calls: %lu\n", drains);
fprintf(stderr, "Pages drained: %lu\n", pages);
fprintf(stderr, "Empty transitions: %lu\n", empties);
if (drains > 0) {
fprintf(stderr, "Avg pages/drain: %.2f\n", (double)pages / (double)drains);
}
fprintf(stderr, "================================\n");
}
}
// Register destructor to dump stats on exit
static void mid_inuse_deferred_stats_init(void) __attribute__((constructor));
static void mid_inuse_deferred_stats_init(void) {
atexit(mid_inuse_deferred_stats_dump);
}
#endif // POOL_MID_INUSE_DEFERRED_STATS_BOX_H