A micro-benchmark that disappears, and a sampling blind spot
Measure your machineNeeds C compiler, Python
Problem
Two blind spots of measurement. A micro-benchmark whose result is never used can be removed by the compiler, so it measures nothing and reports an absurdly good time. A sampling profiler sees an event only if a sample lands on it: a 2 ms event once a second is shorter than the 10 ms between samples at 99 Hz, so most occurrences are never sampled, and it is visible only statistically, over many samples.
Part A: a loop that computes x * x for 1 billion values and never uses the result, compiled with -O2; then the same loop with the result summed and printed. Part B: a program that runs a 2 ms sleep about once a second and does busy work otherwise, profiled for 60 seconds at 99 Hz and then 999 Hz (by a timer-signal sampler in the same process). Count how many samples fall in the sleep and how many of the 60 sleeps are seen at all, and the profiler's overhead on the busy work.
The question. What does the unused loop measure, and how much of the short sleep does each sampling rate see?
Predict
Expect an absurdly good time (below 1 ns per iteration, often zero work done) until the result is observable. Expect almost no samples in the sleep at 99 Hz; at 999 Hz both the blind spot and the profiler overhead change.
Run it
1Install uv once. It fetches Python and the lab's packages for you.
Terminal curl -LsSf https://astral.sh/uv/install.sh | sh2Get the script. It is the whole lab: read it, then download it.
View the codeHide the code
a-micro-benchmark-that-disappears-and.py # /// script # requires-python = ">=3.10" # /// # Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT # https://thedataengineering.com/lab-code/LICENSE.txt """A micro-benchmark that disappears, and a profiler's blind spot. Part A: a C loop computes x * x for 1 billion values, first never using the result, then summing it and printing the sum (compiled with -O2; needs cc). Part B: a program sleeps 2 ms about once a second and does busy work otherwise, while a timer-signal sampler records what it is doing at 99 Hz and at 999 Hz. Counts the samples that land in the sleep, and the busy work lost to sampling. """ import argparse, json, os, random, signal, subprocess, tempfile, time p = argparse.ArgumentParser(description=__doc__.splitlines()[0]) p.add_argument("--iter", type=int, default=1_000_000_000, help="Part A: loop iterations.") p.add_argument("--seconds", type=int, default=60, help="Part B: profiled seconds per sampling rate.") p.add_argument("--sleep-ms", type=float, default=2, help="Part B: length of the once-a-second sleep.") p.add_argument("--json", help="Also write the results to this JSON file.") args = p.parse_args() C = r""" #include <stdio.h> #include <time.h> int main(void){ struct timespec a,b; clock_gettime(CLOCK_MONOTONIC,&a); unsigned long sum = 0; for (unsigned long x = 0; x < ITER; x++) { #ifdef OBSERVE sum += x * x; __asm__ volatile("" : "+r"(sum)); /* keeps the compiler from replacing the loop with a formula */ #else unsigned long y = x * x; (void)y; /* never used */ #endif } clock_gettime(CLOCK_MONOTONIC,&b); double s = (b.tv_sec-a.tv_sec)+(b.tv_nsec-a.tv_nsec)/1e9; fprintf(stderr, "sum=%lu\n", sum); printf("%.9f\n", s); } """ d = tempfile.mkdtemp(); src = os.path.join(d, "square.c"); open(src, "w").write(C); part_a = [] for name, flags in (("result never used", []), ("sum printed", ["-DOBSERVE"])): exe = os.path.join(d, "observe" if flags else "unused") subprocess.run(["cc", "-O2", f"-DITER={args.iter}UL", *flags, src, "-o", exe], check=True) sec = float(subprocess.run([exe], capture_output=True, text=True, check=True).stdout) part_a.append({"variant": name, "seconds": sec, "ns_per_iter": sec / args.iter * 1e9}) sleeping = False; samples = {"total": 0, "sleep": 0}; hit_events = set(); event = 0 def sample(signum, frame): samples["total"] += 1 if sleeping: samples["sleep"] += 1; hit_events.add(event) def profiled(hz): global sleeping, event samples.update(total=0, sleep=0); hit_events.clear(); event = 0; work = 0 if hz: signal.signal(signal.SIGALRM, sample); signal.setitimer(signal.ITIMER_REAL, 1 / hz, 1 / hz) start = time.perf_counter(); next_sleep = start + 1 while (now := time.perf_counter()) < start + args.seconds: if now >= next_sleep: event += 1; sleeping = True; time.sleep(args.sleep_ms / 1000); sleeping = False; next_sleep += random.uniform(0.95, 1.05) # about once a second: a fixed 1 s would run in lockstep with the timer for _ in range(1000): work += 1 # busy work signal.setitimer(signal.ITIMER_REAL, 0) return {"rate": f"{hz} Hz" if hz else "no profiler", "hz": hz, "samples": samples["total"], "in_sleep": samples["sleep"], "expected_in_sleep": hz * event * args.sleep_ms / 1000, "sleeps": event, "sleeps_seen": len(hit_events), "work": work} part_b = [profiled(0), profiled(99), profiled(999)] for r in part_b: r["overhead_pct"] = (1 - r["work"] / part_b[0]["work"]) * 100 for r in part_a: print(f"A {r['variant']:<18} {r['seconds']:.4f} s ({r['ns_per_iter']:.4f} ns per iteration)") for r in part_b[1:]: print(f"B {r['rate']:>6}: {r['samples']} samples, {r['in_sleep']} in the sleep (expected {r['expected_in_sleep']:.1f}); " f"{r['sleeps_seen']} of {r['sleeps']} sleeps seen at all; busy work {r['overhead_pct']:.1f}% lower than unprofiled") if args.json: with open(args.json, "w") as f: json.dump({"tables": {"part_a": part_a, "part_b": part_b}}, f)3Run it in the folder you saved it to, with the defaults first. Then change a knob from the table below and run it again.
Terminal uv run a-micro-benchmark-that-disappears-and.py uv run a-micro-benchmark-that-disappears-and.py --help # every knob
| Knob · default | What it changes |
|---|---|
| --iter1,000,000,000 | Part A: loop iterations. |
| --seconds60 | Part B: profiled seconds per sampling rate. |
| --sleep-ms2 | Part B: length of the once-a-second sleep. |
Our run
Part A: one billion x*x
| Variant | Time (s) | ns per iteration |
|---|---|---|
| result never used | 0 | 0 |
| sum printed | 0.328 | 0.328 |
Part B: a 2 ms sleep once a second, 60 s
| Sampling | Samples | In the sleep | Expected | Sleeps seen | Overhead |
|---|---|---|---|---|---|
| no profiler | 0 | 0 | 0 | 0 | 0% |
| 99 Hz | 5.94K | 22 | 11.7 | 22 | -0.089% |
| 999 Hz | 59.9K | 141 | 120 | 60 | 0.415% |
A result never used 0.0000 s (0.0000 ns per iteration)
A sum printed 0.3282 s (0.3282 ns per iteration)
B 99 Hz: 5939 samples, 22 in the sleep (expected 11.7); 22 of 59 sleeps seen at all; busy work -0.1% lower than unprofiled
B 999 Hz: 59879 samples, 141 in the sleep (expected 119.9); 60 of 60 sleeps seen at all; busy work 0.4% lower than unprofiledWhat we found
The unused loop took 0 s: the compiler removed it. Summed and printed, it took 0.328 ns per iteration. At 99 Hz, 22 samples landed in the sleep (about 11.7 expected from its share of time), and only 22 of 59 sleeps were seen at all. At 999 Hz, 60 of 60 were seen, and the profiler cost 0.415% of the busy work, too little to measure here.
Read it
The sleep is not invisible at 99 Hz, it is under-sampled: across a minute its total share is estimated about right, while any single occurrence is likely missed. A profile is a statistical estimate of where time goes, and short rare events need either a higher rate or a longer run, never a single snapshot.