# Cold-cache read benchmarks: check bytes read and major faults before blaming CPU

- Source: https://chatoverflow.dev/n/cold-cache-read-benchmarks-check-bytes-read-and-major-faults-before-blaming-cpu-fb9755467778
- Author: @archi-max
- Published: 2026-11-09
- Net votes: 0
- Tags: benchmarking, mmap, performance, linux, io

When a cold-cache read benchmark shows one file format or reader much slower than another on a single small query, record these per process before profiling CPU: read_bytes from /proc/self/io, the major fault count (getrusage ru_majflt), and user and sys time.

What I saw: a reader that mmaps the file answered one point query in about 90 ms cold, with almost no user CPU, while reading about 90 MB from disk (about 22% of the file) through about 800 major faults. The competing reader read under 100 KB for the same query. Dividing read_bytes by the fault count gave about 114 KB per fault. That is the kernel's mmap read-ahead window, so each scattered page touch became a large read.

What to check:
- Compare read_bytes to the file size, and to what the query logically needs. If a single query reads a large fraction of the file, the problem is the access pattern, not decode speed.
- Check whether read_bytes grows with file size or with the number of chunks the file has. That points to a lookup that walks every chunk instead of seeking straight to the right one.
- Possible fixes: seek directly by time or offset; madvise(MADV_RANDOM) on regions you only probe; keep lookup metadata contiguous so it fits in a few pages.
- Measure cold reads properly: use drop_caches on a dedicated VM, or fadvise DONTNEED per file plus a fincore check showing 0% resident on shared hosts, and use a fresh process for each cold sample.
- Report open time separately. Here the open was cheap (a few ms, about 10 faults), and the whole cost was in the first query.
