Patch 1: Policy Hot Cache
- Add TinyPolicyHot struct (route_kind[8] cached in TLS)
- Eliminate policy_snapshot() calls (~2 memory ops saved)
- Safety: disabled when learner v7 active
- Files: tiny_metadata_cache_env_box.h, tiny_metadata_cache_hot_box.{h,c}
- Integration: malloc_tiny_fast.h route selection
Patch 2: First Page Inline Cache
- Cache current slab page pointer in TLS per-class
- Avoid superslab metadata lookup (1-2 memory ops)
- Fast-path in tiny_legacy_fallback_free_base()
- Files: tiny_first_page_cache.h, tiny_unified_cache.c
- Integration: tiny_legacy_fallback_box.h
Patch 3: Bounds Check Compile-out
- Hardcode unified_cache capacity as MACRO constant
- Eliminate modulo operation (constant fold)
- Macros: TINY_UNIFIED_CACHE_CAPACITY_POW2=11, CAPACITY=2048, MASK=2047
- File: tiny_unified_cache.h
A/B Test Results (Mixed, 10-run):
- Baseline (C2=0): 40.43M ops/s (avg), 40.72M ops/s (median)
- Optimized (C2=1): 40.25M ops/s (avg), 40.29M ops/s (median)
- Improvement: -0.45% (avg), -1.06% (median)
- DECISION: NEUTRAL (within ±1.0% threshold)
- Action: Keep as research box (ENV gate OFF by default)
Cumulative Gain (Phase 2-3):
- B3 (Routing shape): +2.89%
- B4 (Wrapper split): +1.47%
- C3 (Static routing): +2.20%
- C2 (Metadata cache): -0.45%
- Total: ~6.1% (from baseline 37.5M → 39.8M ops/s)
🤖 Generated with Claude Code
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
83 lines
3.1 KiB
C
83 lines
3.1 KiB
C
// tiny_first_page_cache.h
|
|
// Phase 3 C2 Patch 2: First Page Inline Cache
|
|
//
|
|
// Purpose: Cache current slab page pointer in TLS to avoid superslab metadata lookup
|
|
//
|
|
// Design:
|
|
// - TinyFirstPageCache struct: first_page_base + first_page_free_count
|
|
// - Per-class cache (C0-C7)
|
|
// - Fast-path check in free path (before superslab lookup)
|
|
// - Auto-invalidate on refill/retire
|
|
//
|
|
// Integration:
|
|
// - tiny_legacy_fallback_free_base(): Check cache hit before superslab lookup
|
|
// - Refill/retire: Update cache with new page info
|
|
|
|
#ifndef HAK_FRONT_TINY_FIRST_PAGE_CACHE_H
|
|
#define HAK_FRONT_TINY_FIRST_PAGE_CACHE_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "../hakmem_tiny_config.h" // For TINY_NUM_CLASSES
|
|
|
|
// ============================================================================
|
|
// First Page Cache Structure
|
|
// ============================================================================
|
|
|
|
typedef struct {
|
|
void* first_page_base; // Current page base pointer (avoid superslab lookup)
|
|
uint16_t first_page_free_count; // Free slots in current page (hint only)
|
|
} TinyFirstPageCache;
|
|
|
|
// ============================================================================
|
|
// External TLS Variable
|
|
// ============================================================================
|
|
|
|
extern __thread TinyFirstPageCache g_first_page_cache[TINY_NUM_CLASSES];
|
|
|
|
// ============================================================================
|
|
// First Page Cache API
|
|
// ============================================================================
|
|
|
|
/// Check if ptr is in cached first page (fast path hint)
|
|
/// @param class_idx: Size class (0-7)
|
|
/// @param ptr: Pointer to check (BASE pointer)
|
|
/// @param page_size: Page size for this class
|
|
/// @return: true if ptr is in cached page, false otherwise
|
|
__attribute__((always_inline))
|
|
static inline bool tiny_first_page_cache_hit(uint32_t class_idx, void* ptr, size_t page_size) {
|
|
if (class_idx >= TINY_NUM_CLASSES) return false;
|
|
|
|
void* base = g_first_page_cache[class_idx].first_page_base;
|
|
if (base == NULL) return false;
|
|
|
|
// Check if ptr is within [base, base + page_size)
|
|
uintptr_t ptr_addr = (uintptr_t)ptr;
|
|
uintptr_t base_addr = (uintptr_t)base;
|
|
return (ptr_addr >= base_addr) && (ptr_addr < base_addr + page_size);
|
|
}
|
|
|
|
/// Update first page cache (on refill)
|
|
/// @param class_idx: Size class (0-7)
|
|
/// @param base: New page base pointer
|
|
/// @param count: Free slots in page
|
|
__attribute__((always_inline))
|
|
static inline void tiny_first_page_cache_update(uint32_t class_idx, void* base, uint16_t count) {
|
|
if (class_idx >= TINY_NUM_CLASSES) return;
|
|
|
|
g_first_page_cache[class_idx].first_page_base = base;
|
|
g_first_page_cache[class_idx].first_page_free_count = count;
|
|
}
|
|
|
|
/// Invalidate first page cache (on retire or page full)
|
|
/// @param class_idx: Size class (0-7)
|
|
__attribute__((always_inline))
|
|
static inline void tiny_first_page_cache_invalidate(uint32_t class_idx) {
|
|
if (class_idx >= TINY_NUM_CLASSES) return;
|
|
|
|
g_first_page_cache[class_idx].first_page_base = NULL;
|
|
g_first_page_cache[class_idx].first_page_free_count = 0;
|
|
}
|
|
|
|
#endif // HAK_FRONT_TINY_FIRST_PAGE_CACHE_H
|