v0.6.0: scanner performance overhaul
Performance release. The value scanner (first scan and next scan) was rebuilt around the memory pipeline. Results are unchanged, verified against a brute-force reference across every value width, alignment, comparator, and both scan phases, and clean under ASan/UBSan.
Now the fastest memory scanner on Linux
In a same-machine, same-target benchmark, a first scan for a value is about 2x faster than Cheat Engine 7.7 (the official native Linux build) and 30 to 40x faster than scanmem, GameConqueror, and PINCE, with larger margins on some scans (up to ~13x vs Cheat Engine, ~145x vs scanmem). Full methodology and how to reproduce it: BENCHMARK.md.
| First scan, 1 GB, exact int32 | Time | Throughput |
|---|---|---|
| This project | 0.085 s | ~12 GB/s |
| Cheat Engine 7.7 (native Linux) | 0.156 s | ~6.6 GB/s |
gdb find |
0.749 s | ~1.4 GB/s |
| scanmem 0.17 / GameConqueror | 2.924 s | ~0.34 GB/s |
| PINCE (libmemscan) | 3.480 s | ~0.29 GB/s |
Typical first-scan lead over CE 7.7 is ~2x; "up to" figures are best cases. One machine (i5-10500H, 12 threads); CE timed excluding its GUI startup. GameConqueror uses scanmem's engine; PINCE uses its own Zig backend (libmemscan), benchmarked here on exact-value scans (it is reportedly faster on unknown-value scans, not covered here).
What changed
- Cache-blocked first scan (~3x): memory is read in L2-sized chunks so the scan runs from cache, not RAM.
- Every core on one region: a single large mapping is now split across threads (was single-threaded).
- Skip reserved/untouched pages via
/proc/pid/pagemap(resident-only reads). - SIMD for exact and rounded numeric scans and for byte-pattern (AOB / string) scans.
- Next scan: batched, multithreaded, and coalesced reads (millions of tiny reads become large transfers).
- Compact result storage: 4-byte offset addresses, no duplicated first-value stream.
Full details under "Performance" in CHANGELOG.md.
Install
The .deb and AppImage below are built by CI. The .deb/AppImage set cap_sys_ptrace, so scanning works without root.