# Factorio Benchmark Results

**Platform:** {{platform}}
**Factorio Version:** {{factorio_version}}
**Date:** {{date}}

## Scenario
* Each save was tested for {{ticks}} tick(s) and {{runs}} run(s)

## Results
| Metric            | Description                           |
| ----------------- | ------------------------------------- |
| **Mean UPS**      | Updates per second – higher is better |
| **Mean Avg (ms)** | Average frame time – lower is better  |
| **Mean Min (ms)** | Minimum frame time – lower is better  |
| **Mean Max (ms)** | Maximum frame time – lower is better  |

| Save | Avg (ms) | Min (ms) | Max (ms) | UPS | Execution Time (ms) | % Difference from base |
|------|----------|----------|----------|-----|---------------------|------------------------|
{{#each results}}
| {{save_name}} | {{avg_ms}} | {{min_ms}} | {{max_ms}} | {{{avg_effective_ups}}} | {{total_execution_time_ms}} | {{percentage_improvement}} |
{{/each}}

{{#if results.0.mimalloc}}
## Memory (mimalloc)

### What these numbers mean (practical interpretation)
| Field | What it roughly indicates |
|------|----------------------------|
| **Committed (peak)** | Highest amount of memory backed by the OS during the run (best "memory footprint" trend metric). |
| **Reserved (peak)** | Highest virtual address space reserved by the allocator. **If Committed > Reserved, the application uses direct `mmap`/`VirtualAlloc` outside the allocator** (e.g., for memory-mapped files or custom pools). |
| **Peak RSS** | Highest resident set size (what was actually in RAM). Large gaps between Committed and RSS indicate sparse memory usage (hugepages, memory-mapped files, or reserved-but-untouched arenas). |
| **Commit Efficiency** | `(Peak RSS / Committed Peak)` as percentage. <10% = sparse allocation (mostly reserved, not touched); >80% = dense working set. |
| **Committed/Reserved (current)** | What the allocator still held at process exit. Not automatically a leak—mimalloc retains arenas for reuse. **Trend this across multiple runs; growth between identical runs indicates leaks.** |
| **Pages / Abandoned (current + status)** | "Not all freed" is **normal**—the allocator caches pages for reuse. Abandoned blocks indicate thread-local heap fragments from terminated threads. Flag only if these numbers grow across benchmark iterations. |
| **Thread Churn** | `(Threads Peak - Current)`. Values >0 indicate short-lived worker threads spawned during initialization (explains Abandoned blocks). |
| **Threads (peak)** | Peak allocator thread count observed. If Peak > Current, expect elevated Abandoned blocks. |
| **mmaps** | Number of OS allocation calls. Low counts (<50) with high memory usage indicate efficient arena reuse. High counts indicate frequent allocation pressure or fragmentation. |
| **purges / resets** | Memory returned to OS. Usually 0 in benchmarks—non-zero indicates aggressive memory trimming or constrained environments. |

### Summary (end-of-run heap stats)
| Save | Committed Peak | Peak RSS | Commit Efficiency | Reserved Peak | Committed Current | Reserved Current | Pages Current | Pages Status | Abandoned Current | Abandoned Status | Thread Churn | Threads Peak | mmaps | purges | resets |
|------|----------------|----------|-------------------|---------------|-------------------|------------------|---------------|-------------|-------------------|------------------|--------------|-------------|-------|--------|--------|
{{#each results}}
{{#each mimalloc}}
| {{../save_name}} | {{committed_peak}} | {{peak_rss}} | {{commit_efficiency}} | {{reserved_peak}} | {{committed_current}} | {{reserved_current}} | {{pages_current}} | {{pages_status}} | {{abandoned_current}} | {{abandoned_status}} | {{thread_churn}} | {{threads_peak}} | {{mmaps}} | {{purges}} | {{resets}} |
{{/each}}
{{/each}}

{{/if}}
## Conclusion
