skip to content

Records per second is unchanged but each step of the job now takes twice as long — which further measurements separate the causes?

level: middleimportance: should knowfreq 55%

answer

  1. a count is not a volume
  2. bytes per record, bytes per piece
  3. did every step slow, or one
  4. averages hide a heavy few

basics

~20 s

Read bytes per second beside records per second, plus bytes per record. A flat record rate with doubled step duration usually means fatter records, more input per piece, or slower machines — three different fixes, separated by the volume figures and by the spread across pieces.

solid answer

~40 s

Records per second is a count; it says nothing about how much data moved. I would put three more figures beside it. **Bytes per second and bytes per record**, which catch a payload or schema change that doubled the volume without changing the count. **Input volume per piece and the number of pieces**, because the same total input cut into half as many pieces doubles the work each worker process does. And **the duration spread across pieces within the slow step** — if every piece doubled, the machines or the data volume changed; if a handful doubled and the rest are normal, that is uneven work and a different owner entirely. Reading only the record rate is how a job that is quietly moving twice the bytes gets diagnosed as a capacity problem.

go deeper

for a junior

Remember that throughput has two units. Records per second and bytes per second are separate figures, and a job can be in trouble with one of them perfectly steady.

for a middle

Explain the mechanism: the same record count can carry twice the bytes, the same total input cut into fewer pieces doubles the work per worker, and slower machines move every step by the same factor.

for a senior

Show the routing. Say which figure sends you to uneven work, which to memory pressure, and which to the pool your run is sharing, and do it without changing anything first.

for a principal

Decide which of these figures is worth retaining per run for a year, and what it costs the organisation when nobody can compare today's run against the same job three months ago.

## Two rates that are not the same rate **Processed throughput** is not one number. Records per second counts items; bytes per second counts volume. They move independently, and the gap between them is where most of this diagnosis lives. - Records per second flat, bytes per second up: the records themselves grew. A new field, a nested structure, an upstream producer that started attaching a payload it used not to. - Records per second up, bytes per second flat: more, smaller records. Per-record overhead now dominates, which usually shows up as time rather than volume. - Both flat, duration up: the work per record grew, or the machines got slower. A *step* here is one transformation in the job's graph, applied to every piece of the input, and a *piece* is one slice of that input handled by one worker process — one process on one machine that runs pieces of the job and owns the memory they use. ## The three candidate causes When the record rate holds and per-step duration doubles, the honest shortlist is short: 1. **More data behind the same record count.** Fatter records, or a wider row after a change upstream. The tell is bytes per record. 2. **More data behind the same piece.** The total input grew, or the input is being cut into fewer pieces, so each worker process now holds twice as much. The tell is bytes read per piece and the number of pieces, which are two separate figures and can move in opposite directions. 3. **Slower machines.** Contention from other runs in a shared pool, fewer machines than the run usually gets, or hardware that is degraded. The tell is that *every* step slowed by roughly the same factor, including steps whose input did not change at all. ## Measurements that separate them | Figure to read | Cause it confirms | Cause it eliminates | |---|---|---| | bytes per record, against the last normal run | fatter records | fewer pieces; slower machines | | bytes read per piece, and the piece count | more input per worker | a record-shape change | | the same factor on every step, including trivial ones | slower or fewer machines | anything data-shaped | | duration spread across pieces inside the slow step | a few heavy pieces rather than all of them | a uniform volume increase | | bytes spilled to a worker's local disk | a working set that stopped fitting in memory | a pure arithmetic slowdown | The fourth row is the one candidates skip. A step's duration is usually reported as a total or an average, and an average hides the case where three pieces out of four hundred did all the extra work. Reading the spread costs nothing and changes the answer. ## What varies by execution model The phrase 'per-step duration' does not mean the same thing across this family of engines, so say which model you are on before quoting one. - On a **continuous job built from repeated small finite runs**, where the engine slices an endless input into small finite jobs run back to back, you get a fresh set of per-step durations every slice. Comparing slice against slice is easy, and a slice that outgrows its own period is the real alarm. - On a **record-at-a-time runtime with key-bound state**, where a record moves through the graph as it arrives, there is no repeated boundary to time. What you read instead is the fraction of its time each step spends busy, and the volume figures per step per second. - On the **two-phase disk-to-disk model**, where every phase writes its whole output to shared storage before the next reads it, the natural unit is a phase, which may contain several graph steps. A doubled phase there can hide a single step that got much worse. Whatever figures a given engine publishes, and on whatever screen, the quantities above are the ones to look for; the names attached to them are the engine's business. ## Where the diagnosis hands off This is a reading exercise, and its job is to hand the problem to the right owner rather than to solve it. - A few pieces far heavier than the rest is **uneven work across pieces**, and reading that spread properly is its own subject. - A step whose in-memory queue keeps filling because something after it cannot keep up is **resistance in the graph**, and tracing it back to the step that actually caused it is a separate exercise. - Rising spilled bytes is a **memory** question: how one worker's memory is divided, and what it writes to local disk when a working set will not fit, are owned elsewhere. What this exercise owns is the discipline of never answering 'records per second is fine' as though that settled anything. A job can move twice the data, at the same record rate, with every dashboard reporting a steady figure, right up until a worker runs out of room.

  • The record rate is flat and bytes per second is flat, but one step still doubled. What now?
    The work per record grew, or the machines did less per second. Look for a change in what that one step does — a lookup added, a more expensive comparison, a wider grouping key — then check whether the same factor appears on steps whose logic did not change. If it does, it is the machines or the pool, not the code.
  • Why is the number of pieces worth reading beside the volume?
    Total input and pieces set the work per worker between them. Halving the piece count with constant input doubles what each worker process holds, which lengthens each unit of work and can push a working set past the point where it fits in memory. The record rate can stay flat through all of that.

saying these in an interview costs you the question

  • Treats records per second as a complete picture of throughput.
  • Concludes 'we need more machines' without checking bytes per record.
  • Reads a step's average duration and never the spread across pieces.
  • Assumes the input volume is constant because the record count is.
  • Confuses fewer pieces with less total data.