# Phase 2b: Adaptive TLS Cache Sizing - Quick Start **Status**: ✅ **IMPLEMENTED** (2025-11-08) **Expected Impact**: +3-10% performance, -30-50% memory --- ## What Was Implemented **Adaptive TLS cache sizing** that automatically grows/shrinks per-class cache based on usage: - **Hot classes** (high usage) → grow to 2048 slots - **Cold classes** (low usage) → shrink to 16 slots - **Initial capacity**: 64 slots (down from 256) --- ## Files Created 1. **`core/tiny_adaptive_sizing.h`** - Header with API and inline helpers 2. **`core/tiny_adaptive_sizing.c`** - Implementation of grow/shrink/adapt logic ## Files Modified 1. **`core/tiny_alloc_fast.inc.h`** - Capacity check, refill clamping, tracking 2. **`core/hakmem_tiny_init.inc`** - Init call 3. **`core/hakmem_tiny.c`** - Header include 4. **`Makefile`** - Add `tiny_adaptive_sizing.o` to all build targets **Total**: 319 new lines + 19 modified lines = **338 lines** --- ## How To Use ### Build ```bash # Full rebuild (recommended after pulling changes) make clean && make larson_hakmem # Or just rebuild adaptive sizing module make tiny_adaptive_sizing.o ``` ### Run ```bash # Default: Adaptive sizing enabled with logging ./larson_hakmem 10 8 128 1024 1 12345 4 # Disable adaptive sizing (use fixed 64 slots) HAKMEM_ADAPTIVE_SIZING=0 ./larson_hakmem 10 8 128 1024 1 12345 4 # Enable adaptive sizing but suppress logs HAKMEM_ADAPTIVE_LOG=0 ./larson_hakmem 10 8 128 1024 1 12345 4 ``` --- ## Expected Logs ``` [ADAPTIVE] Adaptive sizing initialized (initial_cap=64, min=16, max=2048) [TLS_CACHE] Grow class 4: 64 → 128 slots (grow_count=1) [TLS_CACHE] Grow class 4: 128 → 256 slots (grow_count=2) [TLS_CACHE] Grow class 4: 256 → 512 slots (grow_count=3) [TLS_CACHE] Keep class 1 at 64 slots (usage=45.2%) [TLS_CACHE] Shrink class 0: 64 → 32 slots (shrink_count=1) ``` **Interpretation**: - **Class 4 grows**: High allocation rate → needs more cache - **Class 1 stable**: Moderate usage → keep current size - **Class 0 shrinks**: Low usage → reclaim memory --- ## How It Works ### 1. Initialization - All classes start at 64 slots (reduced from 256) - Stats reset: `high_water_mark=0`, `refill_count=0` ### 2. Tracking (on every refill) - Update `high_water_mark` if current count > previous peak - Increment `refill_count` ### 3. Adaptation (every 10 refills or 1 second) - Calculate usage ratio: `high_water_mark / capacity` - **If usage > 80%**: Grow (capacity *= 2, max 2048) - **If usage < 20%**: Shrink (capacity /= 2, min 16) - **Else**: Keep current size (log usage %) ### 4. Enforcement - Before refill: Check `available_capacity = capacity - current_count` - If full: Skip refill (return 0) - Else: Clamp `refill_count = min(wanted, available)` --- ## Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `HAKMEM_ADAPTIVE_SIZING` | 1 | Enable/disable adaptive sizing (1=on, 0=off) | | `HAKMEM_ADAPTIVE_LOG` | 1 | Enable/disable adaptation logs (1=on, 0=off) | --- ## Testing Checklist - [x] Code compiles successfully (`tiny_adaptive_sizing.o`) - [x] Integration compiles (`hakmem_tiny.o`) - [ ] Full build works (`larson_hakmem`) - **Blocked by L25 pool error (unrelated)** - [ ] Logs show adaptive behavior (grow/shrink based on usage) - [ ] Hot class (e.g., 4) grows to 512+ slots - [ ] Cold class (e.g., 0) shrinks to 16-32 slots - [ ] Performance improvement measured (+3-10% expected) - [ ] Memory reduction measured (-30-50% expected) --- ## Known Issues ### ⚠️ L25 Pool Build Error (Unrelated) **Error**: `hakmem_l25_pool.c:1097:36: error: 'struct ' has no member named 'freelist'` **Impact**: Blocks full `larson_hakmem` build **Cause**: L25 pool struct mismatch (NOT caused by Phase 2b) **Workaround**: Fix L25 pool separately OR use simpler benchmarks ### Alternatives for Testing 1. **Build only adaptive sizing module**: ```bash make tiny_adaptive_sizing.o hakmem_tiny.o ``` 2. **Use simpler benchmarks** (if available): ```bash make bench_tiny ./bench_tiny ``` 3. **Create minimal test** (100-line standalone): ```c #include "core/tiny_adaptive_sizing.h" // ... simple alloc/free loop to trigger adaptation ``` --- ## Next Steps 1. **Fix L25 pool error** (separate task) 2. **Run Larson benchmark** to verify behavior 3. **Measure performance** (+3-10% expected) 4. **Measure memory** (-30-50% expected) 5. **Implement Phase 2b.1**: SuperSlab integration for block return --- ## Quick Reference ### Key Functions - `adaptive_sizing_init()` - Initialize all classes to 64 slots - `grow_tls_cache(class_idx)` - Double capacity (max 2048) - `shrink_tls_cache(class_idx)` - Halve capacity (min 16) - `adapt_tls_cache_size(class_idx)` - Decide grow/shrink/keep - `update_high_water_mark(class_idx)` - Track peak usage - `track_refill_for_adaptation(class_idx)` - Called after every refill ### Key Constants - `TLS_CACHE_INITIAL_CAPACITY = 64` (was 256) - `TLS_CACHE_MIN_CAPACITY = 16` - `TLS_CACHE_MAX_CAPACITY = 2048` - `GROW_THRESHOLD = 0.8` (80%) - `SHRINK_THRESHOLD = 0.2` (20%) - `ADAPT_REFILL_THRESHOLD = 10` refills - `ADAPT_TIME_THRESHOLD_NS = 1s` --- **Full Report**: See `/mnt/workdisk/public_share/hakmem/PHASE2B_IMPLEMENTATION_REPORT.md` **Spec**: See `/mnt/workdisk/public_share/hakmem/PHASE2B_TLS_ADAPTIVE_SIZING.md`