Files
hakmem/core/box/ss_addr_map_box.h
Moe Charm (CI) 87b7d30998 Phase 9: SuperSlab optimization & EMPTY slab recycling (WIP)
Phase 9-1: O(1) SuperSlab lookup optimization
- Created ss_addr_map_box: Hash table (8192 buckets) for O(1) SuperSlab lookup
- Created ss_tls_hint_box: TLS caching layer for SuperSlab hints
- Integrated hash table into registry (init, insert, remove, lookup)
- Modified hak_super_lookup() to use new hash table
- Expected: 50-80 cycles → 10-20 cycles (not verified - SuperSlab disabled by default)

Phase 9-2: EMPTY slab recycling implementation
- Created slab_recycling_box: SLAB_TRY_RECYCLE() macro following Box pattern
- Integrated into remote drain (superslab_slab.c)
- Integrated into TLS SLL drain (tls_sll_drain_box.h) with touched slab tracking
- Observable: Debug tracing via HAKMEM_SLAB_RECYCLE_TRACE
- Updated Makefile: Added new box objects to 3 build targets

Known Issues:
- SuperSlab registry exhaustion still occurs (unregistration not working)
- shared_pool_release_slab() may not be removing from g_super_reg[]
- Needs investigation before Phase 9-2 can be completed

Expected Impact (when fixed):
- Stage 1 hit rate: 0% → 80%
- shared_fail events: 4 → 0
- Kernel overhead: 55% → 15%
- Throughput: 16.5M → 25-30M ops/s (+50-80%)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 07:16:50 +09:00

149 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ss_addr_map_box.h - Phase 9-1: SuperSlab Address Map Box
// Purpose: O(1) address → SuperSlab* mapping (replace linear search)
// Contract: Fast lookup with hash table (O(1) amortized, upgrade to true O(1) later)
//
// Box Pattern:
// - Single Responsibility: Address→SuperSlab mapping ONLY
// - Clear Contract: ss_map_lookup(ptr) returns SuperSlab* in O(1) amortized
// - Observable: Debug macros log all lookups in non-release builds
// - Composable: Can coexist with legacy registry during migration
//
// Performance Target:
// - Current: Linear search 50-80 cycles
// - Phase 9-1: Hash table ~10-20 cycles
// - Future: 2-tier page table ~5-10 cycles (Phase 9-2)
#ifndef HAK_BOX_SS_ADDR_MAP_H
#define HAK_BOX_SS_ADDR_MAP_H
#include <stddef.h>
#include <stdint.h>
#include "../hakmem_build_flags.h"
// Forward declaration
struct SuperSlab;
// ============================================================================
// Hash Table Entry (Chaining for collision resolution)
// ============================================================================
typedef struct SSMapEntry {
void* base; // SuperSlab base address (key)
struct SuperSlab* ss; // SuperSlab pointer (value)
struct SSMapEntry* next; // Chain for collisions
} SSMapEntry;
// ============================================================================
// Address Map Structure
// ============================================================================
// Hash table size: 8192 buckets (2^13)
// - Trade-off: Memory vs collision rate
// - 8K buckets × 8 bytes = 64KB (acceptable overhead)
// - Load factor target: <2 entries/bucket average
#define SS_MAP_HASH_SIZE 8192
typedef struct {
SSMapEntry* buckets[SS_MAP_HASH_SIZE]; // Hash table buckets
size_t count; // Total entries (for stats)
size_t collisions; // Collision counter (for stats)
} SSAddrMap;
// ============================================================================
// API Functions
// ============================================================================
// Initialize map (call once at startup)
void ss_map_init(SSAddrMap* map);
// Insert SuperSlab into map
// Precondition: base must be SuperSlab-aligned (512KB/1MB/2MB)
// Contract: O(1) insertion
void ss_map_insert(SSAddrMap* map, void* base, struct SuperSlab* ss);
// Lookup SuperSlab by pointer
// Contract: O(1) amortized lookup
// Returns: SuperSlab* if found, NULL if not found
struct SuperSlab* ss_map_lookup(SSAddrMap* map, void* ptr);
// Remove SuperSlab from map
// Contract: O(1) amortized removal
void ss_map_remove(SSAddrMap* map, void* base);
// Shutdown map (free all entries)
void ss_map_shutdown(SSAddrMap* map);
// ============================================================================
// Statistics (Debug builds only)
// ============================================================================
#if !HAKMEM_BUILD_RELEASE
// Print map statistics (count, collisions, load factor)
void ss_map_print_stats(SSAddrMap* map);
// Get collision rate (for performance tuning)
double ss_map_collision_rate(SSAddrMap* map);
#endif
// ============================================================================
// Debug Macros (Observable Box Pattern)
// ============================================================================
#if !HAKMEM_BUILD_RELEASE
#define SS_MAP_LOOKUP(map, ptr) \
({ \
void* _ptr = (ptr); \
struct SuperSlab* _ss = ss_map_lookup(map, _ptr); \
if (getenv("HAKMEM_SS_MAP_TRACE")) { \
fprintf(stderr, "[SS_MAP_LOOKUP] ptr=%p -> ss=%p\n", _ptr, (void*)_ss); \
} \
_ss; \
})
#define SS_MAP_INSERT(map, base, ss) \
do { \
if (getenv("HAKMEM_SS_MAP_TRACE")) { \
fprintf(stderr, "[SS_MAP_INSERT] base=%p ss=%p\n", (void*)(base), (void*)(ss)); \
} \
ss_map_insert(map, base, ss); \
} while(0)
#define SS_MAP_REMOVE(map, base) \
do { \
if (getenv("HAKMEM_SS_MAP_TRACE")) { \
fprintf(stderr, "[SS_MAP_REMOVE] base=%p\n", (void*)(base)); \
} \
ss_map_remove(map, base); \
} while(0)
#else
// Release builds: Direct function calls (no overhead)
#define SS_MAP_LOOKUP(map, ptr) ss_map_lookup(map, ptr)
#define SS_MAP_INSERT(map, base, ss) ss_map_insert(map, base, ss)
#define SS_MAP_REMOVE(map, base) ss_map_remove(map, base)
#endif
// ============================================================================
// Hash Function (Internal, exposed for testing)
// ============================================================================
// Hash pointer to bucket index
// Strategy: Use upper bits (SuperSlab-aligned, lower bits are 0)
// - ptr >> 19 (min SuperSlab size 512KB = 2^19)
// - & (SS_MAP_HASH_SIZE - 1) for modulo
static inline size_t ss_map_hash(void* ptr) {
uintptr_t addr = (uintptr_t)ptr;
// Shift by 19 bits (512KB alignment minimum)
// Then mask to table size
return (addr >> 19) & (SS_MAP_HASH_SIZE - 1);
}
// ============================================================================
// Global Instance (TLS or Global, TBD in Phase 9-1-4)
// ============================================================================
// For now: Global instance (shared across threads, needs lock)
// Phase 9-1-4: Consider TLS instance for lock-free access
extern SSAddrMap g_ss_addr_map;
#endif // HAK_BOX_SS_ADDR_MAP_H