Performance Achievements: - Tiny allocations: +180-280% (21M → 59-70M ops/s random mixed) - Single-thread: +24% (2.71M → 3.36M ops/s Larson) - 4T stability: 0% → 95% (19/20 success rate) - Overall: 91.3% of System malloc average (target was 40-55%) ✓ Phase 7 (Tasks 1-3): Core Optimizations - Task 1: Header validation removal (Region-ID direct lookup) - Task 2: Aggressive inline (TLS cache access optimization) - Task 3: Pre-warm TLS cache (eliminate cold-start penalty) Result: +180-280% improvement, 85-146% of System malloc Critical Bug Fixes: - Fix 64B allocation crash (size-to-class +1 for header) - Fix 4T wrapper recursion bugs (BUG #7, #8, #10, #11) - Remove malloc fallback (30% → 50% stability) Phase 2a: SuperSlab Dynamic Expansion (CRITICAL) - Implement mimalloc-style chunk linking - Unlimited slab expansion (no more OOM at 32 slabs) - Fix chunk initialization bug (bitmap=0x00000001 after expansion) Files: core/hakmem_tiny_superslab.c/h, core/superslab/superslab_types.h Result: 50% → 95% stability (19/20 4T success) Phase 2b: TLS Cache Adaptive Sizing - Dynamic capacity: 16-2048 slots based on usage - High-water mark tracking + exponential growth/shrink - Expected: +3-10% performance, -30-50% memory Files: core/tiny_adaptive_sizing.c/h (new) Phase 2c: BigCache Dynamic Hash Table - Migrate from fixed 256×8 array to dynamic hash table - Auto-resize: 256 → 512 → 1024 → 65,536 buckets - Improved hash function (FNV-1a) + collision chaining Files: core/hakmem_bigcache.c/h Expected: +10-20% cache hit rate Design Flaws Analysis: - Identified 6 components with fixed-capacity bottlenecks - SuperSlab (CRITICAL), TLS Cache (HIGH), BigCache/L2.5 (MEDIUM) - Report: DESIGN_FLAWS_ANALYSIS.md (11 chapters) Documentation: - 13 comprehensive reports (PHASE*.md, DESIGN_FLAWS*.md) - Implementation guides, test results, production readiness - Bug fix reports, root cause analysis Build System: - Makefile: phase7 targets, PREWARM_TLS flag - Auto dependency generation (-MMD -MP) for .inc files Known Issues: - 4T stability: 19/20 (95%) - investigating 1 failure for 100% - L2.5 Pool dynamic sharding: design only (needs 2-3 days integration) 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
5.2 KiB
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
core/tiny_adaptive_sizing.h- Header with API and inline helperscore/tiny_adaptive_sizing.c- Implementation of grow/shrink/adapt logic
Files Modified
core/tiny_alloc_fast.inc.h- Capacity check, refill clamping, trackingcore/hakmem_tiny_init.inc- Init callcore/hakmem_tiny.c- Header includeMakefile- Addtiny_adaptive_sizing.oto all build targets
Total: 319 new lines + 19 modified lines = 338 lines
How To Use
Build
# Full rebuild (recommended after pulling changes)
make clean && make larson_hakmem
# Or just rebuild adaptive sizing module
make tiny_adaptive_sizing.o
Run
# 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_markif 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
- Code compiles successfully (
tiny_adaptive_sizing.o) - 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 <anonymous>' 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
-
Build only adaptive sizing module:
make tiny_adaptive_sizing.o hakmem_tiny.o -
Use simpler benchmarks (if available):
make bench_tiny ./bench_tiny -
Create minimal test (100-line standalone):
#include "core/tiny_adaptive_sizing.h" // ... simple alloc/free loop to trigger adaptation
Next Steps
- Fix L25 pool error (separate task)
- Run Larson benchmark to verify behavior
- Measure performance (+3-10% expected)
- Measure memory (-30-50% expected)
- Implement Phase 2b.1: SuperSlab integration for block return
Quick Reference
Key Functions
adaptive_sizing_init()- Initialize all classes to 64 slotsgrow_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/keepupdate_high_water_mark(class_idx)- Track peak usagetrack_refill_for_adaptation(class_idx)- Called after every refill
Key Constants
TLS_CACHE_INITIAL_CAPACITY = 64(was 256)TLS_CACHE_MIN_CAPACITY = 16TLS_CACHE_MAX_CAPACITY = 2048GROW_THRESHOLD = 0.8(80%)SHRINK_THRESHOLD = 0.2(20%)ADAPT_REFILL_THRESHOLD = 10refillsADAPT_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