Theory

The crossover: four answers

Now compare your guess with the measurement.

$ algo sweep -ints
key: int32   layout: contiguous

     n |   lin cmps   bin cmps |    lin ns/op    bin ns/op | winner by CLOCK
-------|-----------------------|---------------------------|----------------
     2 |          2          2 |            2            3 | LINEAR
     4 |          3          2 |            3            3 | binary
     8 |          5          3 |            3            3 | binary
    16 |          9          4 |            4            4 | binary
    32 |         17          5 |            5            4 | binary
   127 |         65          7 |           22            7 | binary
  1024 |        513         10 |          112            5 | binary
  2254 |       1128         11 |          265            6 | binary

The counter and the clock disagree

Look at n = 4: 3 comparisons against 2, and identical times. At n = 8 the counter says binary is 1.7× better; the clock says they are level. The gap only opens much later.

By comparisons, binary wins almost immediately. By the clock, only from n ≈ 6.

Neither is lying. They measure different things:

  • a comparison is the unit Big-O counts;
  • time depends on what one comparison costs, on whether the data is already in the processor's cache, and on whether the processor can predict where the next jump goes.

A linear scan walks the array in order. The processor sees that pattern coming and fetches ahead. A binary search jumps: n/2, n/4, 3n/4 — and every jump is unpredictable.

So 65 predictable comparisons can take less time than 7 unpredictable ones.

And there is more than one answer

Run the same sweep with a different layout and key:

configuration crossover
-ints, contiguous (this page) n ≈ 6
-ints -scattered (through a map, like a real index) n ≈ 6, but both ~2× slower
without -ints (strings, expensive comparison) n ≈ 3

With strings, one comparison is a function call that may walk several bytes. When comparisons get expensive, the linear scan — which makes n/2 of them — loses sooner.

Three mechanisms, each of which moves the crossover: memory layout, the cost of one comparison, and how well the processor predicts branches.

Four answers to one question

transit measured this question two ways and got two answers. We measured it a third time and got a third:

measurement crossover
transit, synthetic contiguous array ≈ 50
transit, real timetable, their machine > 127 (linear still winning)
transit's benchmark, our machine < 127 (binary winning)
this lesson, our machine ≈ 6

From 6 to more than 127. A twentyfold spread for the same algorithm.

transit's synthetic run used a fresh contiguous []int32 sitting in cache; its real index reaches the same kind of array through a 1,514-entry map. Layout decided the winner, not the algorithm.

Your number will be the fifth

Run algo sweep on your own machine. You will almost certainly get a different number again.

That is not a mistake. That is the answer.

If your crossover differs from the one printed here, you have not done anything wrong — you have reproduced the actual finding: the crossover is not a property of the algorithm. It is a property of your data, your layout and your processor.

The skill this lesson is after is not the number 50 or 127. It is being able to find yours.

Gotcha

The one number that does not move is the comparison count: 11 comparisons for 2,254 items, wherever you run it. That is why this course counts operations. But the decision about which search to use is made by the clock — and the clock has to be run on your own machine.