12 Performance Numbers Every Developer Should Measure Once
Twelve small, reproducible measurements across Java, Go, Python, JavaScript, SQL and Linux, with the numbers, the setup and the caveats behind each one.
These are numbers I measured on my own machine while building and reviewing systems. Each links to a page with the exact setup and caveats. Every one is a single run on one machine, so read them as direction.
Which patterns have the biggest effect?
1. Repeated scans. Checking membership in a list inside a loop is quadratic. In Java, 10,000 lookups in 100,000 items took 1,762 ms with ArrayList.contains and 0.25 ms with HashSet.contains (details). In JavaScript, Array.includes took 386.6 ms against 0.56 ms for Set.has (details).
2. Missing indexes. A lookup on 5 million rows took 403 ms with a full scan and 0.06 ms with an index in SQLite, with a 3.8 s one-time build (details).
3. N+1 queries. Loading 2,000 authors' books one query at a time issued 2,001 queries (47.7 ms in-process); one JOIN took 2.8 ms, and a network database makes the gap worse (details).
Which patterns are about copying and allocation?
4. String building in a loop. In Go, 50,000 appends with += allocated 1.35 GB and took 163.9 ms; strings.Builder took 0.18 ms (details). Java shows the same shape: 448 ms against 0.5 ms (details).
5. Slice growth. Preallocating capacity in Go cut 39 allocations to 1 and 4.49 ms to 0.95 ms (details).
6. Lists versus generators. Summing 5 million squares peaked at 204 MB with a Python list comprehension and under 1 MB with a generator (details).
Which patterns are about waiting?
7. Sequential awaits. Ten independent 100 ms calls took 1.01 s one by one and 0.10 s with Promise.all (details). Python's asyncio.gather showed the same effect for 100 simulated calls: 10.4 s versus 0.10 s (details).
8. Caching in front of a slow backend. With nginx proxy_cache, a 200 ms backend went from 69.8 to 868.2 requests per second and from 200 backend hits to 1 (details).
Which patterns are about bytes?
9. Compression. A 2.72 MB JSON response became 0.34 MB with gzip and 0.25 MB with brotli (details).
10. Image formats. A flat graphic was 2.89 MB as PNG and 0.07 MB as WebP (details).
11. Columnar files. A 1.35 GB CSV became a 0.43 GB Parquet file, and the same query dropped from 6.3 s to 1.8 s (details).
And one tooling number?
12. Type-check time. On a generated 400-file project, TypeScript 7.0.2 type-checked in about 1.9 s where 5.9.3 took about 18.8 s (details).
How should I use these?
Pick the one that matches something your profiler already shows, re-run the small script on your machine, and decide with your own numbers. The full benchmark index has more, including Linux topics such as cron versus systemd timers and capping journal size.
FAQ
- Are these micro-benchmarks reliable?
- They show direction, not exact production numbers. Each page states the machine, the setup and the limits, and the code is small enough to re-run on your own hardware.
- Where do I start if I want to speed up a real system?
- Profile first. These patterns help when your profile shows them, not by default.
Join the Newsletter
Subscribe to get my latest content by email.
We won't send you spam. Unsubscribe at any time.