Tiny: add per-class refill count tuning infrastructure (ChatGPT)

External AI (ChatGPT Pro) implemented hierarchical refill count tuning:
- Move getenv() from hot path to init (performance hygiene)
- Add per-class granularity: global → hot/mid → per-class precedence
- Environment variables:
  * HAKMEM_TINY_REFILL_COUNT (global default)
  * HAKMEM_TINY_REFILL_COUNT_HOT (classes 0-3)
  * HAKMEM_TINY_REFILL_COUNT_MID (classes 4-7)
  * HAKMEM_TINY_REFILL_COUNT_C{0..7} (per-class override)

Performance impact: Neutral (no tuning applied yet, default=16)
- Larson 4-thread: 4.19M ops/s (unchanged)
- No measurable overhead from init-time parsing

Code quality improvement:
- Better separation: hot path reads plain ints (no syscalls)
- Future-proof: enables A/B testing per size class
- Documentation: ENV_VARS.md updated

Note: Per Ultrathink's advice, further tuning deferred until bottleneck
visualization (superslab_refill branch analysis) is complete.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: ChatGPT <external-ai@openai.com>
This commit is contained in:
Moe Charm (CI)
2025-11-05 17:45:11 +09:00
parent 4978340c02
commit 5ea6c1237b
4 changed files with 60 additions and 7 deletions

View File

@ -5,6 +5,7 @@
#pragma once
#include "tiny_atomic.h"
#include "hakmem_tiny.h"
#include <stdio.h>
// ========== Debug Counters (compile-time gated) ==========
#if HAKMEM_DEBUG_COUNTERS
@ -43,6 +44,12 @@ extern int sll_refill_small_from_ss(int class_idx, int max_take);
extern void* hak_tiny_alloc_slow(size_t size, int class_idx);
extern int hak_tiny_size_to_class(size_t size);
// Global Front refill config (parsed at init; defined in hakmem_tiny.c)
extern int g_refill_count_global;
extern int g_refill_count_hot;
extern int g_refill_count_mid;
extern int g_refill_count_class[TINY_NUM_CLASSES];
// External macros
#ifndef HAK_RET_ALLOC
#define HAK_RET_ALLOC(cls, ptr) return (ptr)
@ -157,18 +164,29 @@ static inline void* tiny_alloc_fast_pop(int class_idx) {
static inline int tiny_alloc_fast_refill(int class_idx) {
uint64_t start = tiny_profile_enabled() ? tiny_fast_rdtsc() : 0;
// Tunable refill count (cached in TLS for performance)
static __thread int s_refill_count = 0;
if (__builtin_expect(s_refill_count == 0, 0)) {
// Tunable refill count (cached per-class in TLS for performance)
static __thread int s_refill_count[TINY_NUM_CLASSES] = {0};
int cnt = s_refill_count[class_idx];
if (__builtin_expect(cnt == 0, 0)) {
int def = 16; // Default: 16 (smaller = less overhead per refill)
char* env = getenv("HAKMEM_TINY_REFILL_COUNT");
int v = (env ? atoi(env) : def);
int v = def;
// Resolve precedence without getenv on hot path (values parsed at init)
if (g_refill_count_class[class_idx] > 0) {
v = g_refill_count_class[class_idx];
} else if (class_idx <= 3 && g_refill_count_hot > 0) {
v = g_refill_count_hot;
} else if (class_idx >= 4 && g_refill_count_mid > 0) {
v = g_refill_count_mid;
} else if (g_refill_count_global > 0) {
v = g_refill_count_global;
}
// Clamp to sane range (avoid pathological cases)
if (v < 8) v = 8; // Minimum: avoid thrashing
if (v > 256) v = 256; // Maximum: avoid excessive TLS memory
s_refill_count = v;
s_refill_count[class_idx] = v;
cnt = v;
}
#if HAKMEM_DEBUG_COUNTERS
@ -179,7 +197,7 @@ static inline int tiny_alloc_fast_refill(int class_idx) {
// Box Boundary: Delegate to Backend (Box 3: SuperSlab)
// This gives us ACE, Learning layer, L25 integration for free!
// Note: g_rf_hit_slab counter is incremented inside sll_refill_small_from_ss()
int refilled = sll_refill_small_from_ss(class_idx, s_refill_count);
int refilled = sll_refill_small_from_ss(class_idx, cnt);
if (start) {
g_tiny_refill_cycles += (tiny_fast_rdtsc() - start);