Code

Three searches, two ways to measure

Create search.go (see the panel). It holds three searches, timeIt and two commands.

Why every search exists twice

The file has LowerBound and lowerBoundRaw. The same algorithm, except the second has no counter.

That is not lazy duplication. The counter is called once per comparison — n/2 times in the linear scan, log n times in the binary one. Time the code with the counter in it and you penalise the linear scan roughly 250× harder than the binary one.

I measured it both ways. With the counter, the crossover lands at n ≈ 3; without it, at n ≈ 6. The instrument moved the thing it was measuring by a factor of two.

In lesson 4 the counter could not see memory. Here it changes the result. Count with one version, time with the other.

So timeIt calls the ...Raw functions, and the counts are collected separately.

timeIt — the answer to lesson 1's "wall 0s"

func timeIt(d time.Duration, f func()) (time.Duration, int)

A single run cannot be timed — in lesson 1 the clock read 0s. timeIt repeats until at least d has passed, then divides. transit does exactly this, for exactly this reason.

Three searches, one question

LinearAtOrAfter, LowerBound and LowerBoundStd return the same answer. If they did not, comparing their speed would be meaningless.

search_test.go (next step) proves it before any measurement — 620 different targets, all three agreeing. It is the discipline transit follows: prove they are the same function first, then benchmark.