Read an SGLang sweep on an L4
Lesson: Inference Metrics — TTFT, TPOT, ITL, Goodput, P99Cheat sheetTrack: LLM inferenceTrack: Experiment labs
Problem
A serving benchmark gives a table of numbers for each setting. You must read the table and decide. In this lab you read real SGLang 0.5.22 runs of Qwen3-8B on one NVIDIA L4. You find where throughput stops rising, where the latency SLO breaks, what FP8 gives, and whether a smaller prefill chunk helps.
The data comes from manuals/sglang-101/capture/gpu/summary/l4.json in this repository. support.py has a copy of the rows that the lab needs. Each value is the median of three seeds. The MIXED rows also keep the min and max of the three seeds.
Task
Write five helper functions and answers().
gains(ys)returns a float array of length n - 1. Entry i is y_{i+1} / y_i - 1.saturation_point(xs, ys, min_gain=0.05)finds the first step i with gain strictly belowmin_gain. It returnsxs[i], the last level before that step. If no step has a gain belowmin_gain, it returnsxs[-1].largest_within(xs, ys, limit)returns the largestxwhoseyis less than or equal tolimit. If noymeets the limit, it returnsNone.pct_change(new, old)returns 100 \cdot (new - old) / old.ranges_overlap(a, b)takes two dicts with the keys"min"and"max". It returnsTruewhen a_{min} \le b_{max} and b_{min} \le a_{max}.
Then do the experiment in answers(). Use the helpers.
- Change the concurrency from 1 to 64 in
LOAD["default"]. Measureoutput_throughput. Report the saturation point withmin_gain = 0.05assaturation_default. - Do step 1 again for
LOAD["fp8"]. Reportsaturation_fp8. - In
LOAD["default"], measurep99_ttft_msat each concurrency. Report the largest concurrency withp99_ttft_mswithinSLO["ttft_ms"]asslo_concurrency_default. - In
LOAD["default"], measuregoodput_rps. Report the concurrency with the highest goodput asbest_goodput_concurrency_default. If two levels have the same goodput, use the lower concurrency. - At concurrency 32, divide the FP8
output_throughputby the defaultoutput_throughput. Report the ratio asfp8_speedup_c32. - Change the prefill chunk from the default (4096 tokens) to 1024 tokens. Compare
MIXED["chunk-1024"]withMIXED["default"]at the same rate. Use the"median"field. Report the mean over the three rates ofpct_changeinmedian_ttft_msaschunk_ttft_change_pct. Report the same mean foroutput_throughputaschunk_throughput_change_pct. The new value is the chunk 1024 value. The old value is the default value. - For each rate, test if the seed ranges of
median_ttft_msfor the two settings overlap. Report the number of rates with an overlap aschunk_overlap_rates.
Input and output
| Name | Type | Shape | Meaning |
|---|---|---|---|
xs | list of numbers | (n,) | the levels of the variable that you change, in increasing order |
ys | list of floats | (n,) | the measured value at each level, all above 0 for gains |
min_gain | float | scalar | the smallest relative gain that counts as a rise |
limit | float | scalar | the SLO bound, in the unit of ys |
new, old | float | scalar | the changed value and the base value, old is not 0 |
a, b | dict | keys min, max | one seed range each |
gainsreturns a float array of shape(n - 1,).saturation_pointandlargest_withinreturn one element ofxs.largest_withincan returnNone.pct_changereturns a float.ranges_overlapreturns a bool.answers()returns a dict with the eight keys above. Each value is a Pythonfloat.
Constraints
2 <= n <= 20forgainsandsaturation_point.- Do not change the input lists.
- Do not round the answers. The checks accept a relative difference of
1e-6from the reference run. - Use the data in
support.pyonly. Use numpy and the standard library only.
Examples
pythongains([13.42, 31.2, 61.54])text[1.32488823 0.9724359 ]pythonsaturation_point([1, 2, 4, 8], [10.0, 20.0, 20.5, 30.0])text2The gain from 2 to 4 is 0.025, which is below 0.05. The series rises again at 8, but the rule stops at the first low gain.
pythonlargest_within([1, 2, 4, 8], [100.0, 900.0, 1000.0, 1200.0], 1000.0)text4pythonpct_change(37411.99, 35999.18)text3.9245616150145577answers()["saturation_default"] is 32.0.
Provided code: support.py
Your code and the checks import this module with from support import .... You do not change it.
SOURCE = "manuals/sglang-101/capture/gpu/summary/l4.json"
GPU = "NVIDIA L4"
MODELS = {"default": "Qwen/Qwen3-8B", "fp8": "Qwen/Qwen3-8B-FP8 with --kv-cache-dtype fp8_e4m3"}
SLO = {"ttft_ms": 1000.0, "tpot_ms": 100.0}
KV_POOL_TOKENS = {"default": 24094, "fp8": 142369}
LOAD = {
"default": [
{"concurrency": 1, "output_throughput": 13.42, "median_ttft_ms": 189.16, "p99_ttft_ms": 696.1, "median_tpot_ms": 60.16, "goodput_rps": 0.09},
{"concurrency": 2, "output_throughput": 31.2, "median_ttft_ms": 115.43, "p99_ttft_ms": 133.75, "median_tpot_ms": 63.66, "goodput_rps": 0.24},
{"concurrency": 4, "output_throughput": 61.54, "median_ttft_ms": 137.53, "p99_ttft_ms": 139.33, "median_tpot_ms": 64.36, "goodput_rps": 0.48},
{"concurrency": 8, "output_throughput": 112.62, "median_ttft_ms": 170.43, "p99_ttft_ms": 1275.48, "median_tpot_ms": 66.01, "goodput_rps": 0.63},
{"concurrency": 16, "output_throughput": 201.09, "median_ttft_ms": 211.78, "p99_ttft_ms": 2461.58, "median_tpot_ms": 70.11, "goodput_rps": 0.98},
{"concurrency": 32, "output_throughput": 270.11, "median_ttft_ms": 2969.61, "p99_ttft_ms": 4901.04, "median_tpot_ms": 96.18, "goodput_rps": 0.0},
{"concurrency": 64, "output_throughput": 250.85, "median_ttft_ms": 18348.57, "p99_ttft_ms": 33395.92, "median_tpot_ms": 107.42, "goodput_rps": 0.0},
],
"fp8": [
{"concurrency": 1, "output_throughput": 24.53, "median_ttft_ms": 140.72, "p99_ttft_ms": 255.79, "median_tpot_ms": 39.66, "goodput_rps": 0.19},
{"concurrency": 2, "output_throughput": 49.96, "median_ttft_ms": 107.51, "p99_ttft_ms": 110.09, "median_tpot_ms": 39.48, "goodput_rps": 0.39},
{"concurrency": 4, "output_throughput": 98.8, "median_ttft_ms": 101.18, "p99_ttft_ms": 102.56, "median_tpot_ms": 39.96, "goodput_rps": 0.77},
{"concurrency": 8, "output_throughput": 177.43, "median_ttft_ms": 128.01, "p99_ttft_ms": 1055.25, "median_tpot_ms": 40.93, "goodput_rps": 1.17},
{"concurrency": 16, "output_throughput": 313.92, "median_ttft_ms": 147.52, "p99_ttft_ms": 2019.22, "median_tpot_ms": 43.11, "goodput_rps": 1.49},
{"concurrency": 32, "output_throughput": 507.2, "median_ttft_ms": 199.09, "p99_ttft_ms": 3946.51, "median_tpot_ms": 47.73, "goodput_rps": 2.23},
{"concurrency": 64, "output_throughput": 735.91, "median_ttft_ms": 296.42, "p99_ttft_ms": 7903.44, "median_tpot_ms": 56.31, "goodput_rps": 2.87},
],
}
MIXED = {
"default": [
{"rate": 0.5, "output_throughput": {"median": 44.09, "min": 44.06, "max": 44.88}, "median_ttft_ms": {"median": 35999.18, "min": 9752.1, "max": 39340.7}, "p99_itl_ms": {"median": 2578.99, "min": 2480.05, "max": 2863.96}},
{"rate": 1.0, "output_throughput": {"median": 45.44, "min": 45.01, "max": 46.71}, "median_ttft_ms": {"median": 52367.56, "min": 29402.36, "max": 56992.61}, "p99_itl_ms": {"median": 2751.61, "min": 2409.74, "max": 2985.09}},
{"rate": 2.0, "output_throughput": {"median": 46.16, "min": 44.5, "max": 47.54}, "median_ttft_ms": {"median": 59833.66, "min": 39476.3, "max": 67280.64}, "p99_itl_ms": {"median": 2512.47, "min": 2332.1, "max": 3007.5}},
],
"chunk-1024": [
{"rate": 0.5, "output_throughput": {"median": 43.26, "min": 43.11, "max": 43.32}, "median_ttft_ms": {"median": 37411.99, "min": 11475.16, "max": 41100.82}, "p99_itl_ms": {"median": 2922.44, "min": 2766.91, "max": 3066.65}},
{"rate": 1.0, "output_throughput": {"median": 44.78, "min": 43.92, "max": 45.46}, "median_ttft_ms": {"median": 52859.49, "min": 29777.7, "max": 59333.3}, "p99_itl_ms": {"median": 2843.09, "min": 2592.19, "max": 3096.66}},
{"rate": 2.0, "output_throughput": {"median": 43.97, "min": 43.72, "max": 45.72}, "median_ttft_ms": {"median": 62469.02, "min": 41871.45, "max": 69443.92}, "p99_itl_ms": {"median": 2929.75, "min": 2454.91, "max": 3183.3}},
],
}
def column(rows, key):
return [row[key] for row in rows]
Hints
4 hintsSolution and notes
LockedPass every check with Submit to open the reference solution and the notes.
Run it on your computer
Clone the repository, install numpy and run the same checks in a terminal:
python3 scripts/practice/run.py lab-sglang-l4-serving my_answer.py
python3 scripts/practice/run.py lab-sglang-l4-serving my_answer.py --examplesStart my_answer.py from starter.py.
Your code is saved in this browser as you type. On a phone you can read and edit the code, but the checks are easier to use on a desktop.
Keyboard shortcuts
- Ctrl Enter
- Run the examples
- Ctrl Shift Enter
- Submit
- Tab / Shift Tab
- Indent or outdent the lines
- Esc then Tab
- Move the focus out of the editor
- Alt H
- Show the next hint
On a Mac, use Cmd in place of Ctrl.
Select Run to check the examples, or Submit to run every check.