Commit Graph

10 Commits

Author SHA1 Message Date
1010a961fb Tiny: fix header/stride mismatch and harden refill paths
- Root cause: header-based class indexing (HEADER_CLASSIDX=1) wrote a 1-byte
  header during allocation, but linear carve/refill and initial slab capacity
  still used bare class block sizes. This mismatch could overrun slab usable
  space and corrupt freelists, causing reproducible SEGV at ~100k iters.

Changes
- Superslab: compute capacity with effective stride (block_size + header for
  classes 0..6; class7 remains headerless) in superslab_init_slab(). Add a
  debug-only bound check in superslab_alloc_from_slab() to fail fast if carve
  would exceed usable bytes.
- Refill (non-P0 and P0): use header-aware stride for all linear carving and
  TLS window bump operations. Ensure alignment/validation in tiny_refill_opt.h
  also uses stride, not raw class size.
- Drain: keep existing defense-in-depth for remote sentinel and sanitize nodes
  before splicing into freelist (already present).

Notes
- This unifies the memory layout across alloc/linear-carve/refill with a single
  stride definition and keeps class7 (1024B) headerless as designed.
- Debug builds add fail-fast checks; release builds remain lean.

Next
- Re-run Tiny benches (256/1024B) in debug to confirm stability, then in
  release. If any remaining crash persists, bisect with HAKMEM_TINY_P0_BATCH_REFILL=0
  to isolate P0 batch carve, and continue reducing branch-miss as planned.
2025-11-09 18:55:50 +09:00
9cd266c816 refactor: Guard SuperSlab expansion debug logs + Update CURRENT_TASK
## Changes

### 1. Debug Log Cleanup (Release Build Optimization)
**Files Modified:**
- `core/tiny_superslab_alloc.inc.h:183-234`
- `core/hakmem_tiny_superslab.c:567-618`

**Problem:**
- SuperSlab expansion logs flooded output (268+ lines per benchmark run)
- Massive I/O overhead masked true performance in benchmarks
- Production builds should not spam stderr

**Solution:**
- Guard all expansion logs with `#if !defined(NDEBUG) || defined(HAKMEM_SUPERSLAB_VERBOSE)`
- Debug builds: Logs enabled by default
- Release builds: Logs disabled (clean output)
- Can re-enable with `-DHAKMEM_SUPERSLAB_VERBOSE` for debugging

**Guarded Messages:**
- "SuperSlab chunk exhausted for class X, expanding..."
- "Successfully expanded SuperSlabHead for class X"
- "CRITICAL: Failed to expand SuperSlabHead..." (OOM)
- "Expanded SuperSlabHead for class X: N chunks now"

**Impact:**
- Release builds: Clean benchmark output (no log spam)
- Debug builds: Full visibility into expansion behavior
- Performance: No I/O overhead in production benchmarks

### 2. CURRENT_TASK.md Update
**New Focus:** ACE Investigation for Mid-Large Performance Recovery

**Context:**
-  100% stability achieved (commit 616070cf7)
-  Tiny Hot Path: **First time beating BOTH System and mimalloc** (+48.5% vs System)
- 🔴 Critical issue: Mid-Large MT collapsed (-88% vs System)
- Root cause: ACE disabled → all allocations go to mmap (slow)

**Next Task:**
Task Agent to investigate ACE mechanism (Ultrathink mode):
1. Why is ACE disabled?
2. How does ACE improve Mid-Large performance?
3. Can we re-enable ACE to recover +171% advantage?
4. Implementation plan and risk assessment

**Benchmark Results:**
Comprehensive results saved to: `benchmarks/results/comprehensive_20251108_214317/`

---

## Testing

Verified clean build output:
```bash
make clean && make HEADER_CLASSIDX=1 AGGRESSIVE_INLINE=1 PREWARM_TLS=1 larson_hakmem
./larson_hakmem 1 1 128 1024 1 12345 1
# No expansion log spam in release build
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 22:02:09 +09:00
707056b765 feat: Phase 7 + Phase 2 - Massive performance & stability improvements
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>
2025-11-08 17:08:00 +09:00
b7021061b8 Fix: CRITICAL double-allocation bug in trc_linear_carve()
Root Cause:
trc_linear_carve() used meta->used as cursor, but meta->used decrements
on free, causing already-allocated blocks to be re-carved.

Evidence:
- [LINEAR_CARVE] used=61 batch=1 → block 61 created
- (blocks freed, used decrements 62→59)
- [LINEAR_CARVE] used=59 batch=3 → blocks 59,60,61 RE-CREATED!
- Result: double-allocation → memory corruption → SEGV

Fix Implementation:
1. Added TinySlabMeta.carved (monotonic counter, never decrements)
2. Changed trc_linear_carve() to use carved instead of used
3. carved tracks carve progress, used tracks active count

Files Modified:
- core/superslab/superslab_types.h: Add carved field
- core/tiny_refill_opt.h: Use carved in trc_linear_carve()
- core/hakmem_tiny_superslab.c: Initialize carved=0
- core/tiny_alloc_fast.inc.h: Add next pointer validation
- core/hakmem_tiny_free.inc: Add drain/free validation

Test Results:
 bench_random_mixed: 950,037 ops/s (no crash)
 Fail-fast mode: 651,627 ops/s (with diagnostic logs)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 01:18:37 +09:00
d2f0d84584 Phase 6-2.5: Fix SuperSlab alignment bug + refactor constants
## Problem: 53-byte misalignment mystery
**Symptom:** All SuperSlab allocations misaligned by exactly 53 bytes
```
[TRC_FAILFAST_PTR] stage=alloc_ret_align cls=7 ptr=0x..f835
offset=63541 (expected: 63488)
Diff: 63541 - 63488 = 53 bytes
```

## Root Cause (Ultrathink investigation)
**sizeof(SuperSlab) != hardcoded offset:**
- `sizeof(SuperSlab)` = 1088 bytes (actual struct size)
- `tiny_slab_base_for()` used: 1024 (hardcoded)
- `superslab_init_slab()` assumed: 2048 (in capacity calc)

**Impact:**
1. Memory corruption: 64-byte overlap with SuperSlab metadata
2. Misalignment: 1088 % 1024 = 64 (violates class 7 alignment)
3. Inconsistency: Init assumed 2048, but runtime used 1024

## Solution
### 1. Centralize constants (NEW)
**File:** `core/hakmem_tiny_superslab_constants.h`
- `SLAB_SIZE` = 64KB
- `SUPERSLAB_HEADER_SIZE` = 1088
- `SUPERSLAB_SLAB0_DATA_OFFSET` = 2048 (aligned to 1024)
- `SUPERSLAB_SLAB0_USABLE_SIZE` = 63488 (64KB - 2048)
- Compile-time validation checks

**Why 2048?**
- Round up 1088 to next 1024-byte boundary
- Ensures proper alignment for class 7 (1024-byte blocks)
- Previous: (1088 + 1023) & ~1023 = 2048

### 2. Update all code to use constants
- `hakmem_tiny_superslab.h`: `tiny_slab_base_for()` → use `SUPERSLAB_SLAB0_DATA_OFFSET`
- `hakmem_tiny_superslab.c`: `superslab_init_slab()` → use `SUPERSLAB_SLAB0_USABLE_SIZE`
- Removed hardcoded 1024, 2048 magic numbers

### 3. Add class consistency check
**File:** `core/tiny_superslab_alloc.inc.h:433-449`
- Verify `tls->ss->size_class == class_idx` before allocation
- Unbind TLS if mismatch detected
- Prevents using wrong block_size for calculations

## Status
⚠️ **INCOMPLETE - New issue discovered**

After fix, benchmark hits different error:
```
[TRC_FAILFAST] stage=freelist_next cls=7 node=0x...d474
```

Freelist corruption detected. Likely caused by:
- 2048 offset change affects free() path
- Block addresses no longer match freelist expectations
- Needs further investigation

## Files Modified
- `core/hakmem_tiny_superslab_constants.h` - NEW: Centralized constants
- `core/hakmem_tiny_superslab.h` - Use SUPERSLAB_SLAB0_DATA_OFFSET
- `core/hakmem_tiny_superslab.c` - Use SUPERSLAB_SLAB0_USABLE_SIZE
- `core/tiny_superslab_alloc.inc.h` - Add class consistency check
- `core/hakmem_tiny_init.inc` - Remove diet mode override (Phase 6-2.5)
- `core/hakmem_super_registry.h` - Remove debug output (cleaned)
- `PERFORMANCE_INVESTIGATION_REPORT.md` - Task agent analysis

## Next Steps
1. Investigate freelist corruption with 2048 offset
2. Verify free() path uses tiny_slab_base_for() correctly
3. Consider reverting to 1024 and fixing capacity calculation instead

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 21:45:20 +09:00
25a81713b4 Fix: Move g_hakmem_lock_depth++ to function start (27% → 70% success)
**Problem**: After previous fixes, 4T Larson success rate dropped 27% (4/15)

**Root Cause**:
In `log_superslab_oom_once()`, `g_hakmem_lock_depth++` was placed AFTER
`getrlimit()` call. However, the function was already called from within
malloc wrapper context where `g_hakmem_lock_depth = 1`.

When `getrlimit()` or other LIBC functions call `malloc()` internally,
they enter the wrapper with lock_depth=1, but the increment to 2 hasn't
happened yet, so getenv() in wrapper can trigger recursion.

**Fix**:
Move `g_hakmem_lock_depth++` to the VERY FIRST line after early return check.
This ensures ALL subsequent LIBC calls (getrlimit, fopen, fclose, fprintf)
bypass HAKMEM wrapper.

**Result**: 4T Larson success rate improved 27% → 70% (14/20 runs) 
+43% improvement, but 30% crash rate remains (continuing investigation)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 03:03:07 +09:00
77ed72fcf6 Fix: LIBC/HAKMEM mixed allocation crashes (0% → 80% success)
**Problem**: 4T Larson crashed 100% due to "free(): invalid pointer"

**Root Causes** (6 bugs found via Task Agent ultrathink):

1. **Invalid magic fallback** (`hak_free_api.inc.h:87`)
   - When `hdr->magic != HAKMEM_MAGIC`, ptr came from LIBC (no header)
   - Was calling `free(raw)` where `raw = ptr - HEADER_SIZE` (garbage!)
   - Fixed: Use `__libc_free(ptr)` instead

2. **BigCache eviction** (`hakmem.c:230`)
   - Same issue: invalid magic means LIBC allocation
   - Fixed: Use `__libc_free(ptr)` directly

3. **Malloc wrapper recursion** (`hakmem_internal.h:209`)
   - `hak_alloc_malloc_impl()` called `malloc()` → wrapper recursion
   - Fixed: Use `__libc_malloc()` directly

4. **ALLOC_METHOD_MALLOC free** (`hak_free_api.inc.h:106`)
   - Was calling `free(raw)` → wrapper recursion
   - Fixed: Use `__libc_free(raw)` directly

5. **fopen/fclose crash** (`hakmem_tiny_superslab.c:131`)
   - `log_superslab_oom_once()` used `fopen()` → FILE buffer via wrapper
   - `fclose()` calls `__libc_free()` on HAKMEM-allocated buffer → crash
   - Fixed: Wrap with `g_hakmem_lock_depth++/--` to force LIBC path

6. **g_hakmem_lock_depth visibility** (`hakmem.c:163`)
   - Was `static`, needed by hakmem_tiny_superslab.c
   - Fixed: Remove `static` keyword

**Result**: 4T Larson success rate improved 0% → 80% (8/10 runs) 

**Remaining**: 20% crash rate still needs investigation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 02:48:20 +09:00
1da8754d45 CRITICAL FIX: TLS 未初期化による 4T SEGV を完全解消
**問題:**
- Larson 4T で 100% SEGV (1T は 2.09M ops/s で完走)
- System/mimalloc は 4T で 33.52M ops/s 正常動作
- SS OFF + Remote OFF でも 4T で SEGV

**根本原因: (Task agent ultrathink 調査結果)**
```
CRASH: mov (%r15),%r13
R15 = 0x6261  ← ASCII "ba" (ゴミ値、未初期化TLS)
```

Worker スレッドの TLS 変数が未初期化:
- `__thread void* g_tls_sll_head[TINY_NUM_CLASSES];`  ← 初期化なし
- pthread_create() で生成されたスレッドでゼロ初期化されない
- NULL チェックが通過 (0x6261 != NULL) → dereference → SEGV

**修正内容:**
全 TLS 配列に明示的初期化子 `= {0}` を追加:

1. **core/hakmem_tiny.c:**
   - `g_tls_sll_head[TINY_NUM_CLASSES] = {0}`
   - `g_tls_sll_count[TINY_NUM_CLASSES] = {0}`
   - `g_tls_live_ss[TINY_NUM_CLASSES] = {0}`
   - `g_tls_bcur[TINY_NUM_CLASSES] = {0}`
   - `g_tls_bend[TINY_NUM_CLASSES] = {0}`

2. **core/tiny_fastcache.c:**
   - `g_tiny_fast_cache[TINY_FAST_CLASS_COUNT] = {0}`
   - `g_tiny_fast_count[TINY_FAST_CLASS_COUNT] = {0}`
   - `g_tiny_fast_free_head[TINY_FAST_CLASS_COUNT] = {0}`
   - `g_tiny_fast_free_count[TINY_FAST_CLASS_COUNT] = {0}`

3. **core/hakmem_tiny_magazine.c:**
   - `g_tls_mags[TINY_NUM_CLASSES] = {0}`

4. **core/tiny_sticky.c:**
   - `g_tls_sticky_ss[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}`
   - `g_tls_sticky_idx[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}`
   - `g_tls_sticky_pos[TINY_NUM_CLASSES] = {0}`

**効果:**
```
Before: 1T: 2.09M   |  4T: SEGV 💀
After:  1T: 2.41M   |  4T: 4.19M   (+15% 1T, SEGV解消)
```

**テスト:**
```bash
# 1 thread: 完走
./larson_hakmem 2 8 128 1024 1 12345 1
→ Throughput = 2,407,597 ops/s 

# 4 threads: 完走(以前は SEGV)
./larson_hakmem 2 8 128 1024 1 12345 4
→ Throughput = 4,192,155 ops/s 
```

**調査協力:** Task agent (ultrathink mode) による完璧な根本原因特定

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 01:27:04 +09:00
cd6507468e Fix critical SuperSlab accounting bug + ACE improvements
Critical Bug Fix (OOM Root Cause):
- ss_remote_push() was missing ss_active_dec_one() call
- Cross-thread frees did not decrement total_active_blocks
- SuperSlabs appeared "full" even when empty
- hak_tiny_trim() could never free SuperSlabs → OOM
- Result: alloc=49,123 freed=0 bytes=103GB

One-Line Fix (core/hakmem_tiny_superslab.h:360):
+ ss_active_dec_one(ss);  // Decrement on cross-thread free

Impact:
- OOM eliminated (167GB VmSize → clean exit)
- SuperSlabs now properly freed
- Performance maintained: 4.19M ops/s (±0%)
- Memory leak fixed (freed: 0 → expected ~45,000+)

ACE Improvements:
- Set SUPERSLAB_LG_DEFAULT = 21 (2MB, was 1MB)
- g_ss_min_lg_env now uses SUPERSLAB_LG_DEFAULT
- hak_tiny_superslab_next_lg() fallback to default if uninitialized
- Centralized ACE constants in .h for easier tuning

Verification:
- Larson benchmark: Clean completion, no OOM
- Throughput: 4,192,124 ops/s (baseline maintained)

Root cause analysis by Task agent: Larson 50%+ cross-thread frees
triggered accounting leak, preventing SuperSlab reclamation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 22:26:58 +09:00
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