Synthetic fixtures; deterministic local model. No production system is contacted.
Experiment inputs
Complete-run results
Decision trace
What this experiment demonstrates
A container has a CPU limit expressed in millicores. The kernel turns it into a quota of CPU time per period: 1,000 millicores with a 100 ms period is 100 ms of CPU time every 100 ms of wall time, summed over all cores. Requests arrive at a fixed interval, and each needs a fixed amount of CPU that it spreads over a number of threads, up to the cores on the node. Once the quota of a period is spent, every runnable thread waits for the next period. An optional burst lets unused quota accumulate up to a cap and be spent later.
The page simulates two seconds in 1 ms steps and reports each request’s latency next to the latency it would have with no quota, and the counters you would read from cpu.stat: periods with work, throttled periods and time throttled.
Run controlled comparisons
Start with the defaults: a 1,000m limit, a 100 ms period, an 8-core node, and a request every 500 ms needing 200 ms of CPU over 8 threads. Without a quota each request would take 25 ms; with it each takes 113 ms, four of the eight active periods are throttled, and the container uses only 40 percent of its limit on average.
Now change one thing at a time. One thread per request: no throttling, but 200 ms per request because the work is serial. A 2,000m limit or no limit at all: 25 ms. A 20 ms period: 183 ms, because the burst is cut into many throttled slices. A 500m limit: 307 ms. A burst of 100 ms: the median returns to 25 ms while the first request, which has nothing saved, still takes 113 ms. Move the first request 50 ms into a period to see how the position relative to the period boundary changes latency.
Inspect the trace and keep evidence
The request table lists each request’s arrival, its latency and its latency without a quota. Metrics show the median and worst latency, the periods with work, the throttled periods, the time throttled, the average use of the limit and the average cores used. Start trace, Next step, Show all and the slider control how much of the decision trace is visible; the metrics always describe the whole run. Reset restores the defaults and Export JSON downloads the inputs, the table and the trace.
Limits and production translation
The model ignores the kernel’s per-CPU slices, which let a highly threaded group run slightly past its quota, the scheduling of other containers on the node, and the time a thread spends waiting for anything other than CPU. Work is spread perfectly across threads. Use it to understand the shape of the effect, then measure your own containers through cpu.stat or the cAdvisor throttling metrics. What carries over: compare the throttled-period ratio with latency rather than average use, size thread pools from the limit, and choose between a larger limit, no limit, fewer threads and burst deliberately.