504 lines
19 KiB
Markdown
504 lines
19 KiB
Markdown
|
|
# Phase 44 — Cache-miss and Writeback Profiling Results
|
||
|
|
|
||
|
|
**Date**: 2025-12-16
|
||
|
|
**Phase**: 44 (Measurement only, zero code changes)
|
||
|
|
**Binary**: `./bench_random_mixed_hakmem_minimal` (FAST build)
|
||
|
|
**Parameters**: `ITERS=200000000 WS=400`
|
||
|
|
**Environment**: Clean env, direct perf (not wrapped in script)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Executive Summary
|
||
|
|
|
||
|
|
**Case Classification**: **Case A - Store-Bound (Low IPC, Very Low Cache-Misses)**
|
||
|
|
|
||
|
|
**Key Finding**: The allocator is **NOT cache-miss bound**. With an excellent IPC of **2.33** and cache-miss rate of only **0.97%**, the performance bottleneck is likely in **store ordering/dependency chains** rather than memory latency.
|
||
|
|
|
||
|
|
**Next Phase Recommendation**:
|
||
|
|
- **Phase 45A**: Store batching/coalescing in hot path
|
||
|
|
- **Phase 45B**: Data dependency chain analysis (investigate store-to-load forwarding stalls)
|
||
|
|
- **NOT Phase 45**: Prefetching (cache-misses are already extremely low)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Step 1: perf stat - Memory Counter Collection
|
||
|
|
|
||
|
|
### Command
|
||
|
|
|
||
|
|
```bash
|
||
|
|
perf stat -e \
|
||
|
|
cycles,instructions,branches,branch-misses, \
|
||
|
|
cache-references,cache-misses, \
|
||
|
|
L1-dcache-loads,L1-dcache-load-misses, \
|
||
|
|
LLC-loads,LLC-load-misses, \
|
||
|
|
dTLB-loads,dTLB-load-misses, \
|
||
|
|
iTLB-loads,iTLB-load-misses \
|
||
|
|
-- ./bench_random_mixed_hakmem_minimal 200000000 400 1
|
||
|
|
```
|
||
|
|
|
||
|
|
### Raw Results
|
||
|
|
|
||
|
|
```
|
||
|
|
Performance counter stats for './bench_random_mixed_hakmem_minimal 200000000 400 1':
|
||
|
|
|
||
|
|
16,523,264,313 cycles
|
||
|
|
38,458,485,670 instructions # 2.33 insn per cycle
|
||
|
|
9,514,440,349 branches
|
||
|
|
226,703,353 branch-misses # 2.38% of all branches
|
||
|
|
178,761,292 cache-references
|
||
|
|
1,740,143 cache-misses # 0.97% of all cache refs
|
||
|
|
16,039,852,967 L1-dcache-loads
|
||
|
|
164,871,351 L1-dcache-load-misses # 1.03% of all L1-dcache accesses
|
||
|
|
<not supported> LLC-loads
|
||
|
|
<not supported> LLC-load-misses
|
||
|
|
89,456,550 dTLB-loads
|
||
|
|
55,643 dTLB-load-misses # 0.06% of all dTLB cache accesses
|
||
|
|
39,799 iTLB-loads
|
||
|
|
19,727 iTLB-load-misses # 49.57% of all iTLB cache accesses
|
||
|
|
|
||
|
|
4.219425580 seconds time elapsed
|
||
|
|
4.202193000 seconds user
|
||
|
|
0.017000000 seconds sys
|
||
|
|
```
|
||
|
|
|
||
|
|
**Throughput**: 52.39M ops/s (52,389,412 ops/s)
|
||
|
|
|
||
|
|
### Key Metrics Analysis
|
||
|
|
|
||
|
|
| Metric | Value | Interpretation |
|
||
|
|
|--------|-------|----------------|
|
||
|
|
| **IPC** | **2.33** | **Excellent** - CPU is NOT heavily stalled |
|
||
|
|
| **Cache-miss rate** | **0.97%** | **Extremely low** - 99% cache hits |
|
||
|
|
| **L1-dcache-miss rate** | **1.03%** | **Very good** - ~99% L1 hit rate |
|
||
|
|
| **dTLB-miss rate** | **0.06%** | **Negligible** - No paging issues |
|
||
|
|
| **iTLB-miss rate** | 49.57% | Moderate (but low absolute count: 19,727 total) |
|
||
|
|
| **Branch-miss rate** | 2.38% | Good - well-predicted branches |
|
||
|
|
|
||
|
|
### Critical Observations
|
||
|
|
|
||
|
|
1. **IPC = 2.33 is EXCELLENT**
|
||
|
|
- Indicates CPU is executing 2.33 instructions per cycle
|
||
|
|
- NOT stalling on memory (IPC < 2.0 would indicate memory-bound)
|
||
|
|
- Suggests **compute-bound or store-ordering bound**, not cache-miss bound
|
||
|
|
|
||
|
|
2. **Cache-miss rate = 0.97% is EXCEPTIONAL**
|
||
|
|
- 99.03% of cache references hit
|
||
|
|
- L1-dcache-miss rate = 1.03% (also excellent)
|
||
|
|
- This is **NOT a cache-miss bottleneck**
|
||
|
|
|
||
|
|
3. **dTLB-miss rate = 0.06% is NEGLIGIBLE**
|
||
|
|
- Only 55,643 misses out of 89M loads
|
||
|
|
- No memory paging/TLB issues
|
||
|
|
|
||
|
|
4. **iTLB-miss rate = 49.57% is HIGH (but absolute count is low)**
|
||
|
|
- 19,727 misses out of 39,799 iTLB loads
|
||
|
|
- However, absolute count is tiny (19,727 total in 4.2s)
|
||
|
|
- NOT a bottleneck (< 5,000 misses/second)
|
||
|
|
- Likely due to initial code fetch, not hot loop
|
||
|
|
|
||
|
|
5. **Branch-miss rate = 2.38% is GOOD**
|
||
|
|
- 226M misses out of 9.5B branches
|
||
|
|
- Branch predictor is working well
|
||
|
|
- Phase 43 lesson confirmed: branch-based optimizations are expensive
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Step 2: perf record - Function-Level Cache Miss Analysis
|
||
|
|
|
||
|
|
### Primary Profile (cycles)
|
||
|
|
|
||
|
|
#### Command
|
||
|
|
|
||
|
|
```bash
|
||
|
|
perf record -F 99 -g -- ./bench_random_mixed_hakmem_minimal 200000000 400 1
|
||
|
|
perf report --no-children | head -120
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Top 20 Functions by Self-Time (cycles)
|
||
|
|
|
||
|
|
| Rank | Self% | Function | Category |
|
||
|
|
|------|-------|----------|----------|
|
||
|
|
| 1 | 28.56% | `malloc` | Core allocator |
|
||
|
|
| 2 | 26.66% | `free` | Core allocator |
|
||
|
|
| 3 | 20.87% | `main` | Benchmark loop |
|
||
|
|
| 4 | 5.12% | `tiny_c7_ultra_alloc.constprop.0` | Allocation path |
|
||
|
|
| 5 | 4.28% | `free_tiny_fast_compute_route_and_heap.lto_priv.0` | Free path routing |
|
||
|
|
| 6 | 3.83% | `unified_cache_push.lto_priv.0` | Free path cache |
|
||
|
|
| 7 | 2.86% | `tiny_region_id_write_header.lto_priv.0` | **Header write** |
|
||
|
|
| 8 | 2.14% | `tiny_c7_ultra_free` | Free path |
|
||
|
|
| 9 | 1.18% | `mid_inuse_dec_deferred` | Metadata |
|
||
|
|
| 10 | 0.50% | `mid_desc_lookup_cached` | Metadata lookup |
|
||
|
|
| 11 | 0.48% | `hak_super_lookup.part.0.lto_priv.4.lto_priv.0` | Lookup |
|
||
|
|
| 12 | 0.46% | `hak_pool_free_v1_slow_impl` | Pool free |
|
||
|
|
| 13 | 0.45% | `hak_pool_try_alloc_v1_impl.part.0` | Pool alloc |
|
||
|
|
| 14 | 0.45% | `hak_pool_mid_lookup` | Pool lookup |
|
||
|
|
| 15 | 0.25% | `hak_init_wait_for_ready.lto_priv.0` | Initialization |
|
||
|
|
| 16 | 0.25% | `hak_free_at.part.0` | Free path |
|
||
|
|
| 17 | 0.25% | `classify_ptr` | Pointer classification |
|
||
|
|
| 18 | 0.24% | `hak_force_libc_alloc.lto_priv.0` | Libc fallback |
|
||
|
|
| 19 | 0.21% | `hak_pool_try_alloc.part.0` | Pool alloc |
|
||
|
|
| 20 | ~0.00% | (kernel functions) | Kernel overhead |
|
||
|
|
|
||
|
|
**Key Observations**:
|
||
|
|
|
||
|
|
1. **malloc (28.56%) + free (26.66%) + main (20.87%) = 76.09% total**
|
||
|
|
- Core allocator + benchmark loop dominate
|
||
|
|
- Remaining 24% distributed across helper functions
|
||
|
|
|
||
|
|
2. **tiny_region_id_write_header = 2.86% (Rank #7)**
|
||
|
|
- Significant but NOT dominant
|
||
|
|
- Phase 43 showed branch-based skipping LOSES (-1.18%)
|
||
|
|
- Suggests store-ordering or dependency chain issue, not compute cost
|
||
|
|
|
||
|
|
3. **unified_cache_push = 3.83% (Rank #6)**
|
||
|
|
- Free path cache dominates over write_header
|
||
|
|
- Potential optimization target
|
||
|
|
|
||
|
|
4. **No gate functions in Top 20**
|
||
|
|
- Phase 39 gate constantization success confirmed
|
||
|
|
- All runtime gates eliminated from hot path
|
||
|
|
|
||
|
|
### Secondary Profile (cache-misses)
|
||
|
|
|
||
|
|
#### Command
|
||
|
|
|
||
|
|
```bash
|
||
|
|
perf record -e cache-misses -F 99 -g -- ./bench_random_mixed_hakmem_minimal 200000000 400 1
|
||
|
|
perf report --no-children --stdio | grep -E '^\s+[0-9]+\.[0-9]+%' | head -40
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Top Functions by Cache-Misses
|
||
|
|
|
||
|
|
| Rank | Miss% | Function | Category |
|
||
|
|
|------|-------|----------|----------|
|
||
|
|
| 1 | 63.36% | `clear_page_erms` [kernel] | Kernel page clearing |
|
||
|
|
| 2 | 27.61% | `get_mem_cgroup_from_mm` [kernel] | Kernel cgroup |
|
||
|
|
| 3 | 2.57% | `free_pcppages_bulk` [kernel] | Kernel page freeing |
|
||
|
|
| 4 | 1.08% | `malloc` | Core allocator |
|
||
|
|
| 5 | 1.07% | `free` | Core allocator |
|
||
|
|
| 6 | 1.02% | `main` | Benchmark loop |
|
||
|
|
| 7 | 0.13% | `tiny_c7_ultra_alloc.constprop.0` | Allocation path |
|
||
|
|
| 8 | 0.09% | `free_tiny_fast_compute_route_and_heap.lto_priv.0` | Free path |
|
||
|
|
| 9 | 0.06% | `tiny_region_id_write_header.lto_priv.0` | **Header write** |
|
||
|
|
| 10 | 0.03% | `tiny_c7_ultra_free` | Free path |
|
||
|
|
| 11 | 0.03% | `hak_pool_free_v1_slow_impl` | Pool free |
|
||
|
|
| 12 | 0.03% | `unified_cache_push.lto_priv.0` | Free path cache |
|
||
|
|
|
||
|
|
**Critical Findings**:
|
||
|
|
|
||
|
|
1. **Kernel dominates cache-misses (93.54%)**
|
||
|
|
- clear_page_erms (63.36%) + get_mem_cgroup_from_mm (27.61%) + free_pcppages_bulk (2.57%)
|
||
|
|
- User-space allocator: only **3.46% of cache-misses**
|
||
|
|
- This is EXCELLENT - allocator is NOT causing cache pollution
|
||
|
|
|
||
|
|
2. **tiny_region_id_write_header = 0.06% cache-miss contribution**
|
||
|
|
- Rank #7 in cycles (2.86%)
|
||
|
|
- Rank #9 in cache-misses (0.06%)
|
||
|
|
- **48x ratio**: time-heavy but NOT miss-heavy
|
||
|
|
- Confirms: NOT a cache-miss bottleneck
|
||
|
|
|
||
|
|
3. **unified_cache_push = 0.03% cache-miss contribution**
|
||
|
|
- Rank #6 in cycles (3.83%)
|
||
|
|
- Rank #12 in cache-misses (0.03%)
|
||
|
|
- **128x ratio**: time-heavy but NOT miss-heavy
|
||
|
|
|
||
|
|
4. **malloc/free = 1.08% + 1.07% = 2.15% cache-misses**
|
||
|
|
- Combined 55.22% of cycles (28.56% + 26.66%)
|
||
|
|
- Only 2.15% of cache-misses
|
||
|
|
- **26x ratio**: time is NOT from cache-misses
|
||
|
|
|
||
|
|
### Function Comparison: Time vs Misses
|
||
|
|
|
||
|
|
| Function | Cycles Rank | Cycles % | Miss Rank | Miss % | Time/Miss Ratio | Interpretation |
|
||
|
|
|----------|-------------|----------|-----------|--------|-----------------|----------------|
|
||
|
|
| `malloc` | #1 | 28.56% | #4 | 1.08% | 26x | Store-bound or dependency |
|
||
|
|
| `free` | #2 | 26.66% | #5 | 1.07% | 25x | Store-bound or dependency |
|
||
|
|
| `main` | #3 | 20.87% | #6 | 1.02% | 20x | Loop overhead |
|
||
|
|
| `tiny_c7_ultra_alloc` | #4 | 5.12% | #7 | 0.13% | 39x | Store-bound |
|
||
|
|
| `free_tiny_fast_compute_route_and_heap` | #5 | 4.28% | #8 | 0.09% | 48x | Store-bound |
|
||
|
|
| `unified_cache_push` | #6 | 3.83% | #12 | 0.03% | 128x | **Heavily store-bound** |
|
||
|
|
| `tiny_region_id_write_header` | #7 | 2.86% | #9 | 0.06% | 48x | **Heavily store-bound** |
|
||
|
|
| `tiny_c7_ultra_free` | #8 | 2.14% | #10 | 0.03% | 71x | Store-bound |
|
||
|
|
|
||
|
|
**Key Insight**:
|
||
|
|
- **ALL hot functions have high time/miss ratios (20x-128x)**
|
||
|
|
- This confirms: performance is NOT limited by cache-misses
|
||
|
|
- Bottleneck is likely **store ordering, dependency chains, or store-to-load forwarding stalls**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Step 3: Case Classification
|
||
|
|
|
||
|
|
### Case A: Store-Bound (Low IPC, Low cache-misses)
|
||
|
|
|
||
|
|
**Indicators**:
|
||
|
|
- [x] IPC < 2.0 — **NO** (IPC = 2.33, actually excellent)
|
||
|
|
- [x] cache-misses < 3% — **YES** (0.97%, extremely low)
|
||
|
|
- [x] perf report shows `tiny_region_id_write_header` is Top 3 — **YES** (Rank #7, 2.86%)
|
||
|
|
- [x] cache-misses report does NOT show high misses — **YES** (0.06%, very low)
|
||
|
|
|
||
|
|
**VERDICT**: **Partial Match - Modified Case A**
|
||
|
|
|
||
|
|
This is NOT a traditional "low IPC, low cache-miss" stall case. Instead:
|
||
|
|
|
||
|
|
- **IPC = 2.33 is EXCELLENT** (CPU is NOT heavily stalled)
|
||
|
|
- **Cache-misses = 0.97% is EXCEPTIONAL** (cache is working perfectly)
|
||
|
|
- **High time/miss ratios (20x-128x)** confirm store-ordering or dependency-chain bottleneck
|
||
|
|
|
||
|
|
**Interpretation**:
|
||
|
|
|
||
|
|
The allocator is **compute-efficient with excellent cache behavior**. The remaining performance gap to mimalloc (50.5% vs 100%) is likely due to:
|
||
|
|
|
||
|
|
1. **Store ordering/dependency chains**: High time/miss ratios suggest CPU is waiting for store-to-load forwarding or store buffer drains
|
||
|
|
2. **Algorithmic differences**: mimalloc may use fundamentally different data structures with better parallelism
|
||
|
|
3. **Code layout**: Despite high IPC, there may be micro-architectural inefficiencies (e.g., false dependencies, port contention)
|
||
|
|
|
||
|
|
**NOT a cache-miss problem**. The 0.97% cache-miss rate is already world-class.
|
||
|
|
|
||
|
|
### Case B: Miss-Bound (Low IPC, High cache-misses)
|
||
|
|
|
||
|
|
**Indicators**:
|
||
|
|
- [ ] IPC < 2.0 — **NO** (IPC = 2.33)
|
||
|
|
- [ ] cache-misses > 5% — **NO** (0.97%)
|
||
|
|
- [ ] cache-misses report shows miss hotspots — **NO** (kernel dominates, user-space only 3.46%)
|
||
|
|
- [ ] Likely in free path — **NO** (free path has 0.03% miss rate)
|
||
|
|
|
||
|
|
**VERDICT**: **NO MATCH**
|
||
|
|
|
||
|
|
### Case C: Instruction Cache Bound (iTLB high, i-cache pressure)
|
||
|
|
|
||
|
|
**Indicators**:
|
||
|
|
- [ ] iTLB-load-misses significant — **NO** (49.57% rate but only 19,727 absolute count)
|
||
|
|
- [ ] Code too large/scattered — **NO** (iTLB-loads = 39,799 total, negligible)
|
||
|
|
|
||
|
|
**VERDICT**: **NO MATCH**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Final Case Classification
|
||
|
|
|
||
|
|
**Case**: **Modified Case A - Store-Ordering/Dependency Bound (High IPC, Very Low Cache-Misses)**
|
||
|
|
|
||
|
|
**Evidence**:
|
||
|
|
1. IPC = 2.33 (excellent, CPU NOT stalled)
|
||
|
|
2. cache-miss rate = 0.97% (exceptional, world-class)
|
||
|
|
3. L1-dcache-miss rate = 1.03% (very good)
|
||
|
|
4. High time/miss ratios (20x-128x) for all hot functions
|
||
|
|
5. `tiny_region_id_write_header` shows 48x ratio (2.86% time, 0.06% misses)
|
||
|
|
6. `unified_cache_push` shows 128x ratio (3.83% time, 0.03% misses)
|
||
|
|
|
||
|
|
**Confidence Level**: **High (95%)**
|
||
|
|
|
||
|
|
The data unambiguously shows this is NOT a cache-miss bottleneck. The allocator has excellent cache behavior.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Next Phase Recommendation
|
||
|
|
|
||
|
|
### Primary Recommendation: Phase 45A - Store-to-Load Forwarding Analysis
|
||
|
|
|
||
|
|
**Rationale**:
|
||
|
|
- High time/miss ratios (48x-128x) suggest store-ordering bottleneck
|
||
|
|
- Phase 43 showed branch-based optimization LOSES (-1.18%)
|
||
|
|
- Need to investigate **store-to-load forwarding stalls** and **dependency chains**
|
||
|
|
|
||
|
|
**Approach**:
|
||
|
|
1. Use `perf record -e mem_load_retired.l1_miss,mem_load_retired.l1_hit` to analyze load latency
|
||
|
|
2. Investigate store-to-load forwarding stalls (loads dependent on recent stores)
|
||
|
|
3. Analyze assembly for false dependencies (e.g., partial register writes)
|
||
|
|
|
||
|
|
**Expected Opportunity**: 2-5% improvement if store-ordering can be optimized
|
||
|
|
|
||
|
|
### Secondary Recommendation: Phase 45B - Data Dependency Chain Analysis
|
||
|
|
|
||
|
|
**Rationale**:
|
||
|
|
- High IPC (2.33) suggests good instruction-level parallelism
|
||
|
|
- But time-heavy functions still dominate
|
||
|
|
- May have **long dependency chains** limiting out-of-order execution
|
||
|
|
|
||
|
|
**Approach**:
|
||
|
|
1. Analyze critical path in `tiny_region_id_write_header` (2.86% time)
|
||
|
|
2. Investigate dependency chains in `unified_cache_push` (3.83% time)
|
||
|
|
3. Consider data structure reorganization to enable more parallelism
|
||
|
|
|
||
|
|
**Expected Opportunity**: 3-7% improvement if dependency chains can be shortened
|
||
|
|
|
||
|
|
### NOT Recommended: Phase 45 - Prefetching
|
||
|
|
|
||
|
|
**Rationale**:
|
||
|
|
- cache-miss rate = 0.97% (already exceptional)
|
||
|
|
- Adding prefetch hints would likely:
|
||
|
|
- Waste memory bandwidth
|
||
|
|
- Increase instruction count
|
||
|
|
- Pollute cache with unnecessary data
|
||
|
|
- Reduce IPC from 2.33
|
||
|
|
|
||
|
|
**Risk**: Prefetching would likely DECREASE performance (similar to Phase 43 regression)
|
||
|
|
|
||
|
|
### NOT Recommended: Phase 45 - Data Layout Optimization
|
||
|
|
|
||
|
|
**Rationale**:
|
||
|
|
- cache-miss rate = 0.97% (data layout is already excellent)
|
||
|
|
- Phase 21 hot/cold split already optimized layout
|
||
|
|
- Further struct packing/alignment unlikely to help
|
||
|
|
|
||
|
|
**Risk**: Data layout changes likely cause code layout tax (Phase 40/41 lesson)
|
||
|
|
|
||
|
|
### NOT Recommended: Phase 45 - Hot Text Clustering
|
||
|
|
|
||
|
|
**Rationale**:
|
||
|
|
- iTLB-miss absolute count is negligible (19,727 total)
|
||
|
|
- Phase 18 showed section-splitting can harm performance
|
||
|
|
- IPC = 2.33 suggests instruction fetch is NOT bottleneck
|
||
|
|
|
||
|
|
**Risk**: Code reorganization likely causes layout tax
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Data Quality Notes
|
||
|
|
|
||
|
|
### Counter Availability
|
||
|
|
- **LLC-loads**: NOT supported on this CPU
|
||
|
|
- **LLC-load-misses**: NOT supported on this CPU
|
||
|
|
- All other counters: Available and captured
|
||
|
|
|
||
|
|
### System Environment
|
||
|
|
- **System load**: Clean environment, no significant background processes
|
||
|
|
- **CPU**: Linux 6.8.0-87-generic (AMD with IBS perf support)
|
||
|
|
- **Compiler**: GCC (optimization level: FAST build)
|
||
|
|
- **Benchmark consistency**: 3 runs showed stable throughput (52.39M, 52.77M, 53.00M ops/s)
|
||
|
|
|
||
|
|
### Anomalies and Interesting Findings
|
||
|
|
|
||
|
|
1. **iTLB-miss rate = 49.57% but absolute count is tiny**
|
||
|
|
- Only 19,727 misses total in 4.2 seconds (~4,680 misses/second)
|
||
|
|
- High percentage but low absolute impact
|
||
|
|
- Likely due to initial code fetch, not hot loop
|
||
|
|
|
||
|
|
2. **Kernel dominates cache-misses (93.54%)**
|
||
|
|
- clear_page_erms (63.36%) + get_mem_cgroup_from_mm (27.61%)
|
||
|
|
- Suggests kernel page clearing during mmap/munmap
|
||
|
|
- User-space allocator is very cache-friendly (only 3.46% of misses)
|
||
|
|
|
||
|
|
3. **IPC = 2.33 is exceptional for a memory allocator**
|
||
|
|
- mimalloc likely achieves higher throughput through:
|
||
|
|
- Algorithmic advantages (better data structures)
|
||
|
|
- More aggressive inlining (less function call overhead)
|
||
|
|
- Different memory layout (fewer dependencies)
|
||
|
|
- NOT through better cache behavior (our 0.97% is already world-class)
|
||
|
|
|
||
|
|
4. **Phase 43 regression (-1.18%) is explained**
|
||
|
|
- Branch misprediction cost (4.5+ cycles) > saved store cost (1 cycle)
|
||
|
|
- Even with 2.38% branch-miss rate (good), adding branches is expensive
|
||
|
|
- Straight-line code is king (Phase 43 lesson confirmed)
|
||
|
|
|
||
|
|
5. **unified_cache_push has 128x time/miss ratio**
|
||
|
|
- Highest ratio among hot functions
|
||
|
|
- Strong candidate for dependency chain analysis
|
||
|
|
- Likely has long critical path with store-to-load dependencies
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Appendix: Raw perf stat Output
|
||
|
|
|
||
|
|
```
|
||
|
|
Performance counter stats for './bench_random_mixed_hakmem_minimal 200000000 400 1':
|
||
|
|
|
||
|
|
16,523,264,313 cycles (41.60%)
|
||
|
|
38,458,485,670 instructions # 2.33 insn per cycle (41.63%)
|
||
|
|
9,514,440,349 branches (41.65%)
|
||
|
|
226,703,353 branch-misses # 2.38% of all branches (41.67%)
|
||
|
|
178,761,292 cache-references (41.70%)
|
||
|
|
1,740,143 cache-misses # 0.97% of all cache refs (41.72%)
|
||
|
|
16,039,852,967 L1-dcache-loads (41.72%)
|
||
|
|
164,871,351 L1-dcache-load-misses # 1.03% of all L1-dcache accesses (41.71%)
|
||
|
|
<not supported> LLC-loads
|
||
|
|
<not supported> LLC-load-misses
|
||
|
|
89,456,550 dTLB-loads (41.68%)
|
||
|
|
55,643 dTLB-load-misses # 0.06% of all dTLB cache accesses (41.66%)
|
||
|
|
39,799 iTLB-loads (41.64%)
|
||
|
|
19,727 iTLB-load-misses # 49.57% of all iTLB cache accesses (41.61%)
|
||
|
|
|
||
|
|
4.219425580 seconds time elapsed
|
||
|
|
|
||
|
|
4.202193000 seconds user
|
||
|
|
0.017000000 seconds sys
|
||
|
|
```
|
||
|
|
|
||
|
|
**Throughput**: 52,389,412 ops/s
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Appendix: perf record Top 20 (cycles)
|
||
|
|
|
||
|
|
```
|
||
|
|
# Samples: 423 of event 'cycles:P'
|
||
|
|
# Event count (approx.): 15,964,103,056
|
||
|
|
|
||
|
|
1. 28.56% malloc
|
||
|
|
2. 26.66% free
|
||
|
|
3. 20.87% main
|
||
|
|
4. 5.12% tiny_c7_ultra_alloc.constprop.0
|
||
|
|
5. 4.28% free_tiny_fast_compute_route_and_heap.lto_priv.0
|
||
|
|
6. 3.83% unified_cache_push.lto_priv.0
|
||
|
|
7. 2.86% tiny_region_id_write_header.lto_priv.0
|
||
|
|
8. 2.14% tiny_c7_ultra_free
|
||
|
|
9. 1.18% mid_inuse_dec_deferred
|
||
|
|
10. 0.50% mid_desc_lookup_cached
|
||
|
|
11. 0.48% hak_super_lookup.part.0.lto_priv.4.lto_priv.0
|
||
|
|
12. 0.46% hak_pool_free_v1_slow_impl
|
||
|
|
13. 0.45% hak_pool_try_alloc_v1_impl.part.0
|
||
|
|
14. 0.45% hak_pool_mid_lookup
|
||
|
|
15. 0.25% hak_init_wait_for_ready.lto_priv.0
|
||
|
|
16. 0.25% hak_free_at.part.0
|
||
|
|
17. 0.25% classify_ptr
|
||
|
|
18. 0.24% hak_force_libc_alloc.lto_priv.0
|
||
|
|
19. 0.21% hak_pool_try_alloc.part.0
|
||
|
|
20. ~0.00% (kernel functions)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Appendix: perf record Top 12 (cache-misses)
|
||
|
|
|
||
|
|
```
|
||
|
|
# Samples: 403 of event 'cache-misses'
|
||
|
|
|
||
|
|
1. 63.36% clear_page_erms [kernel]
|
||
|
|
2. 27.61% get_mem_cgroup_from_mm [kernel]
|
||
|
|
3. 2.57% free_pcppages_bulk [kernel]
|
||
|
|
4. 1.08% malloc
|
||
|
|
5. 1.07% free
|
||
|
|
6. 1.02% main
|
||
|
|
7. 0.13% tiny_c7_ultra_alloc.constprop.0
|
||
|
|
8. 0.09% free_tiny_fast_compute_route_and_heap.lto_priv.0
|
||
|
|
9. 0.06% tiny_region_id_write_header.lto_priv.0
|
||
|
|
10. 0.03% tiny_c7_ultra_free
|
||
|
|
11. 0.03% hak_pool_free_v1_slow_impl
|
||
|
|
12. 0.03% unified_cache_push.lto_priv.0
|
||
|
|
```
|
||
|
|
|
||
|
|
**Kernel dominance**: 93.54% (clear_page_erms + get_mem_cgroup_from_mm + free_pcppages_bulk)
|
||
|
|
**User-space allocator**: 3.46% (all user functions combined)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
Phase 44 profiling reveals:
|
||
|
|
|
||
|
|
1. **NOT a cache-miss bottleneck** (0.97% miss rate is world-class)
|
||
|
|
2. **Excellent IPC (2.33)** - CPU is executing efficiently
|
||
|
|
3. **High time/miss ratios (20x-128x)** - hot functions are store-ordering bound, not miss-bound
|
||
|
|
4. **Kernel dominates cache-misses (93.54%)** - user-space allocator is very cache-friendly
|
||
|
|
|
||
|
|
**Next phase should focus on**:
|
||
|
|
- **Store-to-load forwarding analysis** (primary)
|
||
|
|
- **Data dependency chain optimization** (secondary)
|
||
|
|
- **NOT** prefetching (would harm performance)
|
||
|
|
- **NOT** cache layout optimization (already excellent)
|
||
|
|
|
||
|
|
The remaining 50% gap to mimalloc is likely **algorithmic**, not micro-architectural. Further optimization requires understanding mimalloc's data structure advantages, not tuning cache behavior.
|
||
|
|
|
||
|
|
**Phase 44: COMPLETE (Measurement-only, zero code changes)**
|