The Concurrency Lab

Cores, workers, CPU time, I/O time and a critical section — five dials over one model. Turn them and watch throughput, latency, utilization and effective parallelism move together. The lab exists to make one thing visible: adding workers is not adding capacity, and a lock does not care how many cores you bought.

SIMULATED
No number on this page was measured. Every figure below comes from a pure model that runs in your browser. The model reproduces the behaviour of real systems — work does not overlap on one core, a critical section serialises whatever fraction of the work it covers, a queue whose arrival rate exceeds its service rate grows without bound — but the figures belong to no real machine, runtime or workload. Read the shape of the curve and the direction of the change; never quote the milliseconds.
The default configuration (4 cores, 8 workers, 10 ms CPU, 20 ms I/O) retires 150/s at 38% CPU in this model. That number is a property of the model, not of any machine.

Concurrency lab

Move one dial at a time and name the constraint before you read the verdict. The verdict is generated from the same numbers as the meters, so prose and figures cannot drift apart.

Concurrency lab
Six knobs, one model. Ask it the only question that matters: does more concurrency help this workload, and what stops it?
SIMULATEDThese numbers describe no real system.

They come from a queueing and contention model inside Engineer Atlas. What is faithful is the behaviour: work that waits benefits from more workers, work that computes does not, a wide critical section pins parallelism near 1 no matter how many cores you buy, and arrivals past capacity produce an unbounded queue rather than a large latency. Real arrivals are burstier than this model assumes, so real systems reach every one of these walls earlier than the sliders suggest. Do not quote a millisecond from this page.

Controls
Cores the process may actually run on. This is the parallelism ceiling.
Threads or tasks in flight. Not the same quantity as cores, and rarely the same number.
Time actually holding a core. This is the only part cores can parallelise.
Waiting while holding no core. This is the part concurrency can hide.
The slice of the CPU work only one task may execute at a time. Clamped to the CPU time.
Offered load. Past capacity the queue has no steady state at all.
Snapshot the current settings, then change one thing. The model is pure, so the “before” column costs nothing to keep.
throughput
150/s
offered 150/s
latency
31 ms
service 30 ms
effective parallelism
2.67
of 4 cores
lock wait
0.0 ms
no critical section
core wait
0.5 ms
queued for a core
switch overhead
0.3 ms
5 switches/task
CPU utilisation38%
Lock utilisation (no critical section)0%
healthy
Retiring 150/s at 38% CPU. Headroom remains; the next constraint appears at about 267/s.
Change one thing · each preset snapshots the current settings first
healthystatus comes from the model’s discriminated result, not from reading the sentence belowSIMULATED

Scheduler timeline

The same configuration as lanes over time. Running, ready, waiting, blocked, idle — the picture that makes 'the CPU is only 30% busy and everything is slow' obvious.

Scheduler timeline
Tasks over cores, one tick per column. Watch which lanes run, which sit ready, and which are blocked on I/O.
Task 1
ready
ready
blocked
ready
Task 2
ready
ready
blocked
ready
ready
ready
ready
Task 3
ready
ready
ready
ready
ready
blocked
Task 4
ready
ready
ready
ready
Task 5
ready
ready
ready
ready
ready
ready
runningreadywaitingblockedidle1 column = 1 scheduler quantum
running now
1 / 1
ready queue
4
blocked on I/O
0
context switches
0
Ready-queue depth4 waiting for a core
One core: exactly one lane is `running` in every column, yet several tasks advance across the run. That is concurrency without parallelism — the definition, drawn.
A switch is counted whenever a core’s occupant changes between columns; the model charges 0.05 ms for each one. Real switch cost depends on the cache footprint the outgoing task leaves behind and is usually worse than a constant. Mechanism lives in Operating Systems — this view is about what the schedule means.
1/40 · tick 1SIMULATED

What the model reproduces faithfully

These are the behaviours worth learning from this page. Each one is a property of concurrent systems, not of this simulator.

Faithful behaviour
  • Work does not overlap on one core. Concurrency without parallelism hides *waiting*; it never adds compute.
  • A critical section serialises whatever fraction of the work it covers, so speedup collapses toward 1 as that fraction grows — no matter how many cores you add.
  • A queue whose arrival rate exceeds its service rate has no steady state. Latency is then not large, it is unbounded — the model says so rather than inventing a number.
  • Workers beyond the point where a shared resource saturates buy nothing and cost context switches.
  • A cycle in a wait-for graph is a deadlock, and no amount of waiting resolves it.
Deliberate simplifications
  • Arrivals are a smooth rate, not a burst process. Real traffic is burstier, so real systems queue earlier than this shows.
  • Context-switch cost is a flat constant. The real cost depends on cache footprint and is usually worse.
  • The speedup model composes Amdahl with a synchronisation term and a bandwidth ceiling. Real curves have more causes and are rarely this smooth.
  • Nothing here knows your language, runtime, OS scheduler or CPU — and all four change the answer.

Where to take a reading next

The lab shows what a configuration does. These pages ask you to decide first.