The quadratic curve
In lesson 1 you wrote algo gen -n 100000 and produced a hundred thousand items
in a second and a half. That number has cost you nothing so far.
Now it will.
$ algo gen -n 1000 -seed 42 -o s1k.jsonl
$ algo sort -in s1k.jsonl
n = 1000, order = shuffled
algorithm comparisons swaps wall
bubble 498680 243513 3.702ms
selection 499500 997 1.087ms
insertion 244506 243513 514µs
A thousand items, half a million comparisons. Imperceptible.
$ algo sort -in s10k.jsonl
n = 10000, order = shuffled
algorithm comparisons swaps wall
bubble 49993289 24883304 454.17ms
selection 49995000 9992 170.587ms
insertion 24893296 24883304 92.225ms
Ten times the data, a hundred times the work. Nearly half a second.
$ algo sort -in s100k.jsonl
n = 100000, order = shuffled
algorithm comparisons swaps wall
bubble 4999895385 2503732834 1m25.751674s
selection 4999950000 99986 41.607048s
insertion 2503832821 2503732834 26.916946s
A minute and a half. Five billion comparisons for one sort.
The curve
| n | bubble comparisons | ratio |
|---|---|---|
| 1,000 | 498,680 | — |
| 10,000 | 49,993,289 | ×100.3 |
| 100,000 | 4,999,895,385 | ×100.0 |
Ten times the n, a hundred times the work. That is O(n²), and the comparison count reproduces it exactly.
The clock and the counter finally agree — almost
In lesson 6 they disagreed: the counter said one thing and the clock another. Here there is so much work that the clock has nothing left to hide.
But not quite:
| n | wall | ratio |
|---|---|---|
| 1,000 | 3.7 ms | — |
| 10,000 | 454 ms | ×123 |
| 100,000 | 85.8 s | ×189 |
The comparison count grew by exactly ×100. The time grew by ×123 and ×189.
Time is growing faster than quadratically. At 100,000 items the slice is about 7 MB and no longer fits in cache, so every comparison starts costing more. You saw the same effect from the other side in lesson 3.
The counter is still the more precise instrument. It is simply no longer the only one that can see the problem.
Why selection sort is the middle one
It makes more comparisons than bubble (4,999,950,000 against 4,999,895,385) and takes half the time.
The answer is in the swaps column: 99,986 against 2,503,732,834. Twenty-five thousand times less data moved.
A comparison is cheap. A swap is three assignments and a struct copy. At two and a half billion of them, they are what the clock is measuring.
Two different operations, two different costs. That is why the
Sortfunctions take two counters and not one.