Skip to content
About
Main content

Time is work divided by the capacity you kept busy

Why is elapsed time not "work divided by capacity", and what are the only three reasons a machine sits idle?

From "work" to "idleness"

Earlier topics in query processing treat a query as a mathematical object. One topic asks what an computes and at what asymptotic cost (a join of two sorted lists costs about n + m comparisons). Another asks which tree of operators is cheapest under estimated row counts. Both reason in units of work: rows touched, bytes scanned, comparisons performed. Both quietly assume that once a plan is chosen, elapsed time is proportional to the work the plan names.

This mechanism is where that assumption breaks, and it breaks in one specific way:

The new constraint is the machine itself: a finite number of cores, a real clock, memory that is not equally near every core, and handoffs between steps that can cost as much as the computation they connect. The constraint that stops mattering is asymptotics. Nothing here changes the complexity class of any algorithm. Every mechanism here is a constant factor between 2× and 100×. Those constants come from three places: per-tuple control-flow overhead, and branch behaviour, and idleness.

A plan that is 2× better than the alternative, executed by a runtime that keeps only 25% of the machine busy, loses to the worse plan run by a runtime that keeps 90% busy. That is Hana's dashboard.


Three idlenesses

Idleness has exactly three causes. This mechanism's three groups of mechanisms are the three answers. It is worth deriving them, because for any mechanism it tells you which bill you are about to receive.

1. Dependency idleness: a unit waits for its producer

A plan is a graph with edges. A consumer cannot work until its producer has made something. The only escape is to overlap producer and consumer, and overlapping needs a buffer between them. The buffer costs memory, and its depth follows (L = λW): to keep a consumer fed across a producer W at rate λ, you need λW units in flight. Execution models are about this idleness. They answer three questions: who owns the thread, what size of unit crosses each edge, and who is allowed to say "not yet".

2. Imbalance idleness: a unit waits for a peer

Many workers run in parallel. At a or a join point, everyone waits for the slowest one. This is forced by variance in task duration plus any synchronization. The escape is smaller work units plus dynamic assignment. The cost is dispatch overhead and lost locality (data that was in a core's cache is no longer used by that core). Parallelism is about this idleness.

3. Exclusion idleness: a unit waits for a shared resource

Workers share a , a scheduler lock or memory bandwidth, and they take turns. This is forced by sharing itself. The escape is to the resource per worker. The cost is duplication and a merge step. This is the coordination cost that limits scaling (the contention and coherency terms of the Universal Scalability Law: workers waiting for each other, and keeping their copies consistent), arriving at the execution level. It is also why the exists at all: partitioning by key is the act of converting exclusion into data movement.

To pay none of the three, you would have to give up global order or determinism. That is the conservation statement of this mechanism: you can move the cost, but you cannot remove it.

GroupIdleness it attacksGoverning constraintUnit of granularityCurrency paid
Execution modelsDependencyA control transfer has a ; a call is not free → batch → column → whole stageMemory for buffers; latency to the first row; code complexity and compile time
ParallelismImbalanceTime at a barrier is the maximum of task times, not the meanPartition → task → Dispatch overhead, lost locality, duplicated work, non-determinism
ShuffleExclusion (and the other two)Edges grow as M × R, while transfer efficiency needs a minimum number of bytes per edgePartition file → block → row batchDisk and network operations, serialization CPU, an intermediate copy of the data, a barrier

Why the shuffle gets its own group

The shuffle earns first-class status for a structural reason, not an empirical one. It is the only operation whose number of edges grows as the product of the two stage widths (M producers × R consumers), rather than linearly with the number of workers. Everything else here has O(n) coordination. The shuffle has O(n²).

The one number to carry through the whole shuffle discussion is:

Compare it to the of the storage or network underneath. That minimum is roughly 2 MB for spinning disk, about 4 MB for , and about 250 KB for NVMe (fast flash drives). The comparison tells you at once whether a shuffle is limited by bandwidth (bytes per second) or by operations (requests per second). It also tells you which of the six shuffle mechanisms in The shuffle is the relevant one. This single division explains , file consolidation and remote shuffle services as the same fix applied at three different places.


The second number: the barrier and the maximum

Consider n tasks that all sit behind a barrier. Each task has a mean duration, and the durations vary. The c is the standard deviation divided by the mean (c = 0.3 means a typical task is about 30% above or below the mean). For light-tailed durations (those without extreme outliers):

tasks behind the barrier
coefficient of variation: standard deviation ÷ mean
c = 0.1c = 0.3c = 0.6
Data table
Stage time ÷ mean task time, by tasks behind a barrier
Tasks nseriesExpected max ÷ mean
2c = 0.11.12×
2.29c = 0.11.13×
2.62c = 0.11.14×
3c = 0.11.15×
3.44c = 0.11.16×
3.93c = 0.11.17×
4.5c = 0.11.17×
5.15c = 0.11.18×
5.9c = 0.11.19×
6.76c = 0.11.2×
7.73c = 0.11.2×
8.85c = 0.11.21×
10.1c = 0.11.22×
11.6c = 0.11.22×
13.3c = 0.11.23×
15.2c = 0.11.23×
17.4c = 0.11.24×
19.9c = 0.11.24×
22.8c = 0.11.25×
26.1c = 0.11.26×
29.9c = 0.11.26×
34.2c = 0.11.27×
39.2c = 0.11.27×
44.9c = 0.11.28×
51.4c = 0.11.28×
58.8c = 0.11.29×
67.3c = 0.11.29×
77.1c = 0.11.29×
88.2c = 0.11.3×
101c = 0.11.3×
116c = 0.11.31×
132c = 0.11.31×
152c = 0.11.32×
174c = 0.11.32×
199c = 0.11.33×
227c = 0.11.33×
260c = 0.11.33×
298c = 0.11.34×
341c = 0.11.34×
391c = 0.11.35×
447c = 0.11.35×
512c = 0.11.35×
586c = 0.11.36×
671c = 0.11.36×
768c = 0.11.36×
879c = 0.11.37×
1.01Kc = 0.11.37×
1.15Kc = 0.11.38×
1.32Kc = 0.11.38×
1.51Kc = 0.11.38×
1.73Kc = 0.11.39×
1.98Kc = 0.11.39×
2.27Kc = 0.11.39×
2.59Kc = 0.11.4×
2.97Kc = 0.11.4×
3.4Kc = 0.11.4×
3.89Kc = 0.11.41×
4.46Kc = 0.11.41×
5.1Kc = 0.11.41×
5.84Kc = 0.11.42×
6.69Kc = 0.11.42×
7.66Kc = 0.11.42×
8.76Kc = 0.11.43×
10Kc = 0.11.43×
11.5Kc = 0.11.43×
13.2Kc = 0.11.44×
15.1Kc = 0.11.44×
17.2Kc = 0.11.44×
19.7Kc = 0.11.44×
22.6Kc = 0.11.45×
25.9Kc = 0.11.45×
29.6Kc = 0.11.45×
33.9Kc = 0.11.46×
38.8Kc = 0.11.46×
44.4Kc = 0.11.46×
50.9Kc = 0.11.47×
58.2Kc = 0.11.47×
66.6Kc = 0.11.47×
76.3Kc = 0.11.47×
87.3Kc = 0.11.48×
100Kc = 0.11.48×
2c = 0.31.35×
2.29c = 0.31.39×
2.62c = 0.31.42×
3c = 0.31.44×
3.44c = 0.31.47×
3.93c = 0.31.5×
4.5c = 0.31.52×
5.15c = 0.31.54×
5.9c = 0.31.57×
6.76c = 0.31.59×
7.73c = 0.31.61×
8.85c = 0.31.63×
10.1c = 0.31.65×
11.6c = 0.31.66×
13.3c = 0.31.68×
15.2c = 0.31.7×
17.4c = 0.31.72×
19.9c = 0.31.73×
22.8c = 0.31.75×
26.1c = 0.31.77×
29.9c = 0.31.78×
34.2c = 0.31.8×
39.2c = 0.31.81×
44.9c = 0.31.83×
51.4c = 0.31.84×
58.8c = 0.31.86×
67.3c = 0.31.87×
77.1c = 0.31.88×
88.2c = 0.31.9×
101c = 0.31.91×
116c = 0.31.92×
132c = 0.31.94×
152c = 0.31.95×
174c = 0.31.96×
199c = 0.31.98×
227c = 0.31.99×
260c = 0.32×
298c = 0.32.01×
341c = 0.32.02×
391c = 0.32.04×
447c = 0.32.05×
512c = 0.32.06×
586c = 0.32.07×
671c = 0.32.08×
768c = 0.32.09×
879c = 0.32.1×
1.01Kc = 0.32.12×
1.15Kc = 0.32.13×
1.32Kc = 0.32.14×
1.51Kc = 0.32.15×
1.73Kc = 0.32.16×
1.98Kc = 0.32.17×
2.27Kc = 0.32.18×
2.59Kc = 0.32.19×
2.97Kc = 0.32.2×
3.4Kc = 0.32.21×
3.89Kc = 0.32.22×
4.46Kc = 0.32.23×
5.1Kc = 0.32.24×
5.84Kc = 0.32.25×
6.69Kc = 0.32.26×
7.66Kc = 0.32.27×
8.76Kc = 0.32.28×
10Kc = 0.32.29×
11.5Kc = 0.32.3×
13.2Kc = 0.32.31×
15.1Kc = 0.32.32×
17.2Kc = 0.32.33×
19.7Kc = 0.32.33×
22.6Kc = 0.32.34×
25.9Kc = 0.32.35×
29.6Kc = 0.32.36×
33.9Kc = 0.32.37×
38.8Kc = 0.32.38×
44.4Kc = 0.32.39×
50.9Kc = 0.32.4×
58.2Kc = 0.32.41×
66.6Kc = 0.32.41×
76.3Kc = 0.32.42×
87.3Kc = 0.32.43×
100Kc = 0.32.44×
2c = 0.61.71×
2.29c = 0.61.77×
2.62c = 0.61.83×
3c = 0.61.89×
3.44c = 0.61.94×
3.93c = 0.61.99×
4.5c = 0.62.04×
5.15c = 0.62.09×
5.9c = 0.62.13×
6.76c = 0.62.17×
7.73c = 0.62.21×
8.85c = 0.62.25×
10.1c = 0.62.29×
11.6c = 0.62.33×
13.3c = 0.62.36×
15.2c = 0.62.4×
17.4c = 0.62.43×
19.9c = 0.62.47×
22.8c = 0.62.5×
26.1c = 0.62.53×
29.9c = 0.62.56×
34.2c = 0.62.59×
39.2c = 0.62.63×
44.9c = 0.62.65×
51.4c = 0.62.68×
58.8c = 0.62.71×
67.3c = 0.62.74×
77.1c = 0.62.77×
88.2c = 0.62.8×
101c = 0.62.82×
116c = 0.62.85×
132c = 0.62.88×
152c = 0.62.9×
174c = 0.62.93×
199c = 0.62.95×
227c = 0.62.98×
260c = 0.63×
298c = 0.63.03×
341c = 0.63.05×
391c = 0.63.07×
447c = 0.63.1×
512c = 0.63.12×
586c = 0.63.14×
671c = 0.63.16×
768c = 0.63.19×
879c = 0.63.21×
1.01Kc = 0.63.23×
1.15Kc = 0.63.25×
1.32Kc = 0.63.27×
1.51Kc = 0.63.3×
1.73Kc = 0.63.32×
1.98Kc = 0.63.34×
2.27Kc = 0.63.36×
2.59Kc = 0.63.38×
2.97Kc = 0.63.4×
3.4Kc = 0.63.42×
3.89Kc = 0.63.44×
4.46Kc = 0.63.46×
5.1Kc = 0.63.48×
5.84Kc = 0.63.5×
6.69Kc = 0.63.52×
7.66Kc = 0.63.54×
8.76Kc = 0.63.56×
10Kc = 0.63.58×
11.5Kc = 0.63.59×
13.2Kc = 0.63.61×
15.1Kc = 0.63.63×
17.2Kc = 0.63.65×
19.7Kc = 0.63.67×
22.6Kc = 0.63.69×
25.9Kc = 0.63.7×
29.6Kc = 0.63.72×
33.9Kc = 0.63.74×
38.8Kc = 0.63.76×
44.4Kc = 0.63.78×
50.9Kc = 0.63.79×
58.2Kc = 0.63.81×
66.6Kc = 0.63.83×
76.3Kc = 0.63.85×
87.3Kc = 0.63.86×
100Kc = 0.63.88×

This is why mitigation is a first-class mechanism and not an operational nicety. It is also the principle "variance costs more than volume" in its sharpest form: here the variance is multiplied by fan-in (the number of tasks behind the barrier).