Implementation:
- Intrusive LIFO tcache layer (L1) before UnifiedCache
- TLS per-class bins (head pointer + count)
- Intrusive next pointers (via tiny_next_store/load SSOT)
- Cap: 64 blocks per class (default)
- ENV: HAKMEM_TINY_TCACHE=0/1 (default: 0, OFF)
A/B Test Results (Mixed 10-run):
- Baseline (TCACHE=0): 51,083,379 ops/s
- Optimized (TCACHE=1): 51,186,838 ops/s
- Mean delta: +0.20% (below +1.0% GO threshold)
- Median delta: +0.59%
Verdict: NEUTRAL - Freeze as research box (default OFF)
Root Cause (v1 wiring incomplete):
- Free side pushes to tcache via unified_cache_push()
- Alloc hot path (tiny_hot_alloc_fast) doesn't consume tcache
- tcache becomes "sink" without alloc-side pop → ROI not measurable
Files:
- Created: core/box/tiny_tcache_{env_box,box}.h, tiny_tcache_env_box.c
- Modified: core/front/tiny_unified_cache.h (integration)
- Modified: core/bench_profile.h (refresh sync)
- Modified: Makefile (build integration)
- Results: docs/analysis/PHASE14_POINTER_CHASE_REDUCTION_1_AB_TEST_RESULTS.md
- v2 Instructions: docs/analysis/PHASE14_POINTER_CHASE_REDUCTION_2_NEXT_INSTRUCTIONS.md
Next: Phase 14 v2 (connect tcache to tiny_front_hot_box alloc/free hot path)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
94 lines
3.1 KiB
C
94 lines
3.1 KiB
C
// ============================================================================
|
|
// Phase 14 v1: Tiny tcache ENV Box (L0)
|
|
// ============================================================================
|
|
//
|
|
// Purpose: ENV gate for tcache-style intrusive LIFO cache
|
|
//
|
|
// Design: docs/analysis/PHASE14_POINTER_CHASE_REDUCTION_1_DESIGN.md
|
|
// Instructions: docs/analysis/PHASE14_POINTER_CHASE_REDUCTION_1_NEXT_INSTRUCTIONS.md
|
|
//
|
|
// Strategy:
|
|
// - Add intrusive LIFO tcache layer before array-based UnifiedCache
|
|
// - Reduce pointer-chase overhead (system malloc tcache pattern)
|
|
// - Hit: head pointer + intrusive next only (no array access)
|
|
//
|
|
// ENV:
|
|
// HAKMEM_TINY_TCACHE=0/1 (default: 0, opt-in)
|
|
// HAKMEM_TINY_TCACHE_CAP=64 (default: 64, per-class capacity)
|
|
//
|
|
// API:
|
|
// tiny_tcache_enabled() -> int
|
|
// tiny_tcache_cap() -> uint16_t
|
|
// tiny_tcache_env_refresh_from_env()
|
|
//
|
|
// Box Theory:
|
|
// - L0: This file (ENV gate, reversible)
|
|
// - L1: tiny_tcache_box.h (intrusive LIFO logic)
|
|
// - L2: tiny_unified_cache.h (integration point)
|
|
//
|
|
// Safety:
|
|
// - ENV-gated (default OFF, opt-in)
|
|
// - Reversible (ENV toggle)
|
|
// - No call site changes (integration inside unified_cache)
|
|
//
|
|
// ============================================================================
|
|
|
|
#ifndef TINY_TCACHE_ENV_BOX_H
|
|
#define TINY_TCACHE_ENV_BOX_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdatomic.h>
|
|
|
|
// ============================================================================
|
|
// Global State (L0)
|
|
// ============================================================================
|
|
|
|
// Cached state: -1 (uninitialized), 0 (disabled), 1 (enabled)
|
|
extern _Atomic int g_tiny_tcache_enabled;
|
|
|
|
// Cached capacity: 0 (uninitialized), >0 (cap value)
|
|
extern _Atomic uint16_t g_tiny_tcache_cap;
|
|
|
|
// ============================================================================
|
|
// Hot Inline API (L0)
|
|
// ============================================================================
|
|
|
|
// Check if tcache is enabled
|
|
// Returns: 1 if enabled, 0 if disabled
|
|
static inline int tiny_tcache_enabled(void) {
|
|
int val = atomic_load_explicit(&g_tiny_tcache_enabled, memory_order_relaxed);
|
|
|
|
if (__builtin_expect(val == -1, 0)) {
|
|
// Lazy init: read ENV once
|
|
extern int tiny_tcache_env_init(void);
|
|
val = tiny_tcache_env_init();
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
// Get tcache capacity per class
|
|
// Returns: capacity (default 64)
|
|
static inline uint16_t tiny_tcache_cap(void) {
|
|
uint16_t cap = atomic_load_explicit(&g_tiny_tcache_cap, memory_order_relaxed);
|
|
|
|
if (__builtin_expect(cap == 0, 0)) {
|
|
// Lazy init: read ENV once
|
|
extern int tiny_tcache_env_init(void);
|
|
tiny_tcache_env_init();
|
|
cap = atomic_load_explicit(&g_tiny_tcache_cap, memory_order_relaxed);
|
|
}
|
|
|
|
return cap;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Cold API (L2)
|
|
// ============================================================================
|
|
|
|
// Refresh ENV cache (called from bench_profile after putenv)
|
|
// Pattern: Same as Phase 8/13 (FREE_STATIC_ROUTE, C7_PRESERVE_HEADER)
|
|
extern void tiny_tcache_env_refresh_from_env(void);
|
|
|
|
#endif // TINY_TCACHE_ENV_BOX_H
|