Files
hakmem/core/hakmem_tiny_mini_mag.h
Moe Charm (CI) 52386401b3 Debug Counters Implementation - Clean History
Major Features:
- Debug counter infrastructure for Refill Stage tracking
- Free Pipeline counters (ss_local, ss_remote, tls_sll)
- Diagnostic counters for early return analysis
- Unified larson.sh benchmark runner with profiles
- Phase 6-3 regression analysis documentation

Bug Fixes:
- Fix SuperSlab disabled by default (HAKMEM_TINY_USE_SUPERSLAB)
- Fix profile variable naming consistency
- Add .gitignore patterns for large files

Performance:
- Phase 6-3: 4.79 M ops/s (has OOM risk)
- With SuperSlab: 3.13 M ops/s (+19% improvement)

This is a clean repository without large log files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 12:31:14 +09:00

149 lines
5.1 KiB
C

#ifndef HAKMEM_TINY_MINI_MAG_H
#define HAKMEM_TINY_MINI_MAG_H
#include <stddef.h>
#include <stdint.h>
// ============================================================================
// Page Mini-Magazine: Fast LIFO Cache (Data Plane)
// ============================================================================
//
// Purpose: Provide O(1) allocation/free on page level
// Design: Intrusive LIFO free-list (mimalloc-style)
// Cost: 1-2 ns per operation (vs 5-6 ns bitmap scan)
//
// Key Insight: Free blocks store next-pointer in first 8 bytes
// No separate metadata needed (zero overhead)
//
// ============================================================================
// ----------------------------------------------------------------------------
// Intrusive LIFO Block
// ----------------------------------------------------------------------------
typedef struct MiniMagBlock {
struct MiniMagBlock* next; // Next free block in LIFO stack
} MiniMagBlock;
// ----------------------------------------------------------------------------
// Mini-Magazine Metadata
// ----------------------------------------------------------------------------
typedef struct {
MiniMagBlock* head; // LIFO stack head (NULL if empty)
uint16_t count; // Current item count [0, capacity]
uint16_t capacity; // Maximum items (16-32 typical)
} PageMiniMag;
// ============================================================================
// Core Operations (Always Inlined for Speed)
// ============================================================================
// ----------------------------------------------------------------------------
// Pop from Mini-Magazine (Fast Path: 1-2 ns)
// ----------------------------------------------------------------------------
//
// Returns: Pointer to free block, or NULL if empty
// Cost: 1-2 ns (two pointer operations in L1 cache)
//
static inline void* mini_mag_pop(PageMiniMag* mag) __attribute__((always_inline));
static inline void* mini_mag_pop(PageMiniMag* mag) {
MiniMagBlock* b = mag->head;
if (!b) return NULL; // Empty
// Pop from LIFO stack
mag->head = b->next;
mag->count--;
return (void*)b;
}
// ----------------------------------------------------------------------------
// Push to Mini-Magazine (Fast Path: 1-2 ns)
// ----------------------------------------------------------------------------
//
// Returns: 1 on success, 0 if magazine is full
// Cost: 1-2 ns (two pointer operations + count check)
//
static inline int mini_mag_push(PageMiniMag* mag, void* ptr) __attribute__((always_inline));
static inline int mini_mag_push(PageMiniMag* mag, void* ptr) {
if (mag->count >= mag->capacity) return 0; // Full
// Push to LIFO stack (intrusive next-pointer)
MiniMagBlock* b = (MiniMagBlock*)ptr;
b->next = mag->head;
mag->head = b;
mag->count++;
return 1;
}
// ----------------------------------------------------------------------------
// Query Operations
// ----------------------------------------------------------------------------
// Check if mini-magazine is empty
static inline int mini_mag_is_empty(const PageMiniMag* mag) {
return mag->count == 0;
}
// Check if mini-magazine is full
static inline int mini_mag_is_full(const PageMiniMag* mag) {
return mag->count >= mag->capacity;
}
// Get available space
static inline int mini_mag_space(const PageMiniMag* mag) {
return mag->capacity - mag->count;
}
// ============================================================================
// Initialization
// ============================================================================
// Initialize mini-magazine (call on slab creation)
static inline void mini_mag_init(PageMiniMag* mag, uint16_t capacity) {
mag->head = NULL;
mag->count = 0;
mag->capacity = capacity;
}
// Reset mini-magazine (clear all items without freeing)
static inline void mini_mag_reset(PageMiniMag* mag) {
mag->head = NULL;
mag->count = 0;
}
// ============================================================================
// Design Notes
// ============================================================================
//
// 1. LIFO Order (Temporal Locality):
// - Most recently freed block = next allocated
// - Excellent L1 cache hit rate (95%+)
// - Hot blocks stay hot (cache-friendly)
//
// 2. Intrusive Design (Zero Overhead):
// - Next-pointer stored in free block itself
// - No separate metadata array needed
// - Memory overhead: 0 bytes
//
// 3. Thread Safety:
// - Owner-only access (no locks needed)
// - Thread-local page has thread-local mini-magazine
// - Remote frees go to separate MPSC queue
//
// 4. Capacity Tuning:
// - Small (8-16): Lower memory, frequent refills
// - Medium (16-32): Balanced (recommended)
// - Large (32-64): Fewer refills, more memory
//
// 5. Integration with Bitmap:
// - Mini-magazine = Data plane (fast path)
// - Bitmap = Control plane (truth)
// - Batch refill amortizes bitmap scan cost
//
// ============================================================================
#endif // HAKMEM_TINY_MINI_MAG_H