LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnInference & Production ScaleServing Benchmark Engineering
📊HardEvaluation & Benchmarks

Serving Benchmark Engineering

Build a reproducible serving benchmark with a frozen arrival trace, explicit streaming timing boundaries, complete failure accounting, and SLO-qualified capacity estimates.

20 min read
Learning path
Step 165 of 196 in the full curriculum
Distributed Inference Data PlaneA/B Testing for LLMs

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

The server finishes more requests per second, but users wait longer for the first word. Some streams pause halfway through. A few fast responses contain invalid tool arguments. Has the new build improved?

A single throughput number can't answer that. A useful serving benchmark preserves the incoming workload, measures the client's experience, and counts which responses actually satisfy the task. It must also notice when the load generator, rather than the server, is overloaded.

Continuous Batching and Scheduling explains why prompt processing and generation compete. GPU Profiling, Correctness, and Benchmarking separates kernel timing from broader execution. Here, the boundary moves outward to the client, gateway, and serving system, including failures and waiting time.

The running example is an incident assistant receiving a burst of mixed requests. The downloadable records are explicitly synthetic. They exercise a real local scorer; they aren't observations from a model, a load generator, or a GPU.

Freeze what arrives and when

A workload needs more than an average prompt length. Keep the prompt or token IDs, output policy, request class, and scheduled arrival for each identity. Include the system prompt, retrieved context, and conversation history that the application actually sends.

Consider these six arrivals:

IDScheduled timePrompt tokensOutput policyShared prefixClass
r010 ms320natural stop, cap 96runbook Ainteractive
r02120 ms336natural stop, cap 96runbook Ainteractive
r03700 ms4,096natural stop, cap 256noneinteractive
r04760 ms280natural stop, cap 64noneinteractive
r05800 ms2,048natural stop, cap 512policy Bbackground
r061,900 ms480natural stop, cap 128runbook Ainteractive

The long prompt at r03 can interfere with the short request arriving 60 ms later. r05 may occupy a decode slot for longer. Prefix reuse can reduce work, but only if the runtime supports it and the cache state permits a hit. Repeating one prompt isn't inherently wrong; it's wrong to represent a cache-friendly test as an unrelated production mix.

Count tokens with the pinned tokenizer and chat template. An output cap isn't an observed output length. Keep both. Forcing exact output lengths, for example by ignoring end-of-sequence (EOS) tokens, can isolate scheduler behavior, but that is a shape-controlled stress test rather than a natural-response quality evaluation.

Generate the realized trace once, save it, and hash the exact bytes. A seed alone doesn't guarantee identical rows across library or tokenizer versions. The six-row download later contains only scheduling metadata, not these prompts; it's a scorer fixture, not a complete workload for replay against an endpoint.

Public traces can help challenge assumptions. BurstGPT reports real arrival and token-length patterns; ServeGen models production workload characteristics with per-client arrival and request-data models.[1]Reference 1BurstGPT: A Real-World Workload Dataset to Optimize LLM Serving Systemshttps://arxiv.org/abs/2401.17644[2]Reference 2ServeGen: Workload Characterization and Generation of Large Language Model Serving in Productionhttps://www.usenix.org/conference/nsdi26/presentation/xiang-servegen Neither makes its traffic representative of your users. Preserve length tails, prompt/output correlation, tenant mix, prefix reuse, and conversation dependencies that matter to your application.

Don't let a slow server turn down its own test

An open-loop generator schedules requests independently of completions. If r04 is due at 760 ms, r03 still running doesn't cancel that arrival.

A closed-loop generator starts another request when a virtual user becomes free. When responses slow down, its offered rate falls. That is appropriate for studying a fixed user population, but it answers a different question from capacity under an external arrival rate.

ModeWhat controls arrivalsSuitable question
Open-loopStored timestamps or an independent clockCan the system sustain this offered workload?
Closed-loopCompletions and user think timeWhat do this many active users experience?
All-at-onceEvery request released at the startHow does the system handle a batch or admission burst?

MLPerf Inference formalizes different scenarios: Single Stream waits for each completion, while Server/Interactive uses Poisson arrivals. Its quality and latency rules are part of a defined benchmark, not labels a custom load test can borrow.[3]Reference 3MLPerf Inference Benchmark Rules.https://github.com/mlcommons/inference_policies/blob/master/inference_rules.adoc

Rate, concurrency, and burstiness aren't interchangeable

In a stable system, Little's Law relates average outstanding requests LLL, admitted arrival rate λ\lambdaλ, and mean time in the same system WWW:[4]Reference 4A Proof for the Queuing Formula: L = lambda Whttps://doi.org/10.1287/opre.9.3.383

L=λWL = \lambda WL=λW

At 3 requests/s and 0.9 seconds average latency, the average outstanding count is 2.7. A client capped at two outstanding requests can't sustain that combination. Even a cap of three may throttle bursts: an average isn't a maximum. Check whether the cap actually binds.

A Poisson process has exponential inter-arrival gaps with coefficient of variation CV=1CV=1CV=1. Regular spacing has CV=0CV=0CV=0. Real traffic can have correlated bursts that neither description captures. Save realized timestamps when replay identity matters.

As checked on September 2, 2026, vllm bench serve exposes --request-rate, --burstiness, and --max-concurrency. Its burstiness is a Gamma shape parameter kkk, with CV=1/kCV=1/\sqrt{k}CV=1/k​: values below one make gaps more variable. Infinite request rate is an all-at-once or concurrency-limited stress mode, not a finite-rate open-loop test.[5]Reference 5Benchmark CLIhttps://docs.vllm.ai/en/stable/benchmarking/cli/

Time-scaling a stored trace is one way to sweep offered rate while preserving order and relative gaps. It also compresses the duration of a fixed-size cohort. Either extend the trace to keep measurement duration comparable or report that changed duration; you can't claim both fixed request count and fixed duration while changing the rate.

Measure the generator's lateness

Keep scheduled_ms and sent_ms in a common client monotonic-clock domain. If a request is scheduled at 760 ms but sent at 1,100 ms, the generator is 340 ms late. Measuring only from send time hides that discrepancy.

Report send-relative latency and scheduled-relative delay separately. Declare a schedule-lag tolerance and invalidate capacity evidence when the generator can't reproduce the offered load. Delayed or unsent requests must not disappear from the workload denominator. This is one form of coordinated omission: the test stops observing the work that should have arrived during a slowdown.

Client and server clocks aren't automatically comparable. Use client timestamps for client latency. Use server-local spans for queueing and compute attribution, or a measured clock-synchronization scheme when joining absolute times across machines.

A client cap of two binds while testing a target of 3 requests/s. The server's measured latency remains low. What does that establish?

Answer

It establishes behavior under the throttled workload, not capacity at 3 requests/s. Keep the delayed arrivals, report schedule lag, and rerun with a generator that can sustain the intended schedule.

Give the run an arrival window and a drain policy

Separate readiness, warmup, measurement, and drain. Warmup may include loading, kernel compilation, CUDA Graph capture, connections, and scheduler initialization. Don't populate prefix caches unless the measured scenario is supposed to begin with those entries warm.

During the measurement arrival window, send the declared workload. When arrivals stop, retain every request until terminal success, rejection, cancellation, error, or timeout. Choose timeouts before the run. A late response doesn't retroactively undo an earlier timeout experienced by the client.

There are two useful but different accounting views:

  • An arrival cohort includes requests scheduled in a half-open window such as [0, 2000) ms. Judge all of their outcomes, including those observed during drain.
  • A wall-clock interval counts completions occurring inside that interval, regardless of when those requests arrived. Track starting and ending outstanding work to interpret it.

Don't divide one population by the other population's elapsed time. For the local exercise, cohort rates use elapsed time from arrival-window start through the later of window end and last terminal outcome. Those finite-run rates include drain and aren't sustainable-capacity estimates.

For sustained load, inspect outstanding work over time and compare admitted, completed, rejected, and timed-out rates. A flat server queue alone isn't enough: aggressive rejection can keep it flat while users fail. Repeat sufficiently long runs to observe relevant warmup, cache, thermal, and traffic cycles.

Time what the protocol actually reveals

Let sss be client send time, t1t_1t1​ first output-token time, tnt_ntn​ final output-token time, and ccc terminal completion time. Assume these token events genuinely have token granularity and use the same clock.

Time to first token (TTFT) measures the initial wait. Inter-token latency (ITL) measures each subsequent gap:

TTFT=t1−s,ITLi=ti−ti−1TTFT = t_1-s, \qquad ITL_i=t_i-t_{i-1}TTFT=t1​−s,ITLi​=ti​−ti−1​

For n>1n>1n>1, request-mean time per output token (TPOT) is:

TPOT=tn−t1n−1TPOT=\frac{t_n-t_1}{n-1}TPOT=n−1tn​−t1​​

End-to-end completion latency is:

E2E=c−sE2E=c-sE2E=c−s

The final token can precede the terminal event, usage metadata, or connection completion. Replacing ccc with tnt_ntn​ silently changes the metric to last-token latency.

For a request sent at zero, token times [240, 280, 320, 440, 480] ms and terminal time 500 ms produce TTFT 240 ms, TPOT 60 ms, and E2E 500 ms. The four gaps are [40, 40, 120, 40] ms. One 120 ms pause is hidden inside the 60 ms mean.

The following calculation checks those definitions. It doesn't run inference.

stream-timing.py
1from math import ceil 2 3tokens = [240, 280, 320, 440, 480] 4sent, terminal = 0, 500 5assert sent <= tokens[0] <= tokens[-1] <= terminal 6gaps = [b - a for a, b in zip(tokens, tokens[1:])] 7assert all(gap >= 0 for gap in gaps) 8print(f"TTFT: {tokens[0] - sent} ms") 9print(f"ITL: {gaps} ms") 10print(f"TPOT: {sum(gaps) / len(gaps):.0f} ms") 11print(f"last-token latency: {tokens[-1] - sent} ms") 12print(f"terminal E2E: {terminal - sent} ms") 13print(f"nearest-rank p99 of four gaps: {sorted(gaps)[ceil(.99 * len(gaps)) - 1]} ms")
Output
1TTFT: 240 ms 2ITL: [40, 40, 120, 40] ms 3TPOT: 60 ms 4last-token latency: 480 ms 5terminal E2E: 500 ms 6nearest-rank p99 of four gaps: 120 ms

For one-token output, there are no inter-token intervals. TPOT is undefined, not zero. Define the eligibility rule before scoring. The supplied scorer treats the TPOT criterion as not applicable for a successful single-token response, while still checking TTFT and quality. An empty successful output is invalid under this lesson's text-response contract; another endpoint might legitimately define empty output differently.

A streaming chunk isn't necessarily a token

A server-sent event (SSE) may contain several tokens, metadata without text, or a fragment whose tokenization depends on later text. TCP reads aren't SSE event boundaries either. An adapter must reconstruct the protocol, recognize its terminal/error events, and preserve timestamps before producing normalized records.

ObservationHonest metricWhat it doesn't prove
First response byteTime to first byteThat output text has started
First content-bearing chunkTime to first content chunkExact first-token emission time
Client text chunksInter-chunk latencyIndividual token ITL
Server token eventsServer token cadenceClient-visible network cadence
Client token-granular eventsClient-observed ITLGPU kernel duration

Dividing a multi-token chunk's delay by its token count invents arrival times. Keep chunk metrics when those are the available observations. The downloadable scorer accepts normalized token events; it isn't an SSE parser and can't manufacture missing granularity.

Smoothness needs the order of events

A long gap isn't always a playback stall. Earlier tokens can arrive ahead of a reading cadence and provide slack. Etalon's fluidity metric uses token deadlines to capture this distinction.[6]Reference 6Etalon: Holistic Performance Evaluation Framework for LLM Inference Systems.https://arxiv.org/abs/2407.07000

For a simple illustration, set a first-token deadline of 300 ms and a cadence of 80 ms. Deadlines for five tokens are [300, 380, 460, 540, 620]. The earlier example meets all five even though one raw ITL is 120 ms. In [300, 380, 460, 580, 620], the fourth token misses its deadline despite mean TPOT being 80 ms.

This illustrates why deadline and gap metrics answer different questions. An implementation of a published fluidity score must also follow its rules for resetting deadlines after a miss. Don't substitute this five-token comparison for that algorithm or for a measured reading-speed requirement.

Keep the denominator visible

Define a request as qualified only when it has terminal success, acceptable output, and the declared latency properties. HTTP 200 or valid JSON alone doesn't establish task correctness. Errors, timeouts, rejected requests, unsent requests, and wrong answers stay in the offered-request denominator.

Two quantities are often both called goodput:

Grequests=qualified requestsdeclared elapsed secondsG_{\text{requests}}=\frac{\text{qualified requests}}{\text{declared elapsed seconds}}Grequests​=declared elapsed secondsqualified requests​

This is a rate of useful completed work for a specified population and interval. A capacity boundary asks which offered rate still meets the declared service-level objective (SLO):

CSLO=max⁡{λ tested:A(λ)≥α ∧ load reproduced ∧ stable}C_{\text{SLO}}=\max\{\lambda\text{ tested}: A(\lambda)\geq\alpha\ \land\ \text{load reproduced}\ \land\ \text{stable}\}CSLO​=max{λ tested:A(λ)≥α ∧ load reproduced ∧ stable}

Here A(λ)A(\lambda)A(λ) is qualified requests divided by all offered requests, and α\alphaα is the required attainment. DistServe uses a goodput definition tied to the maximum rate satisfying TTFT/TPOT attainment requirements per GPU.[7]Reference 7DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving.https://arxiv.org/abs/2401.09670 Name your definition instead of assuming every tool's “goodput” means that capacity boundary.

A system may finish more qualifying requests per second while also failing a larger fraction of incoming requests. Useful-work rate alone then improves, but a 95% attainment promise fails. Divide a fleet rate by GPU count only when comparing a fixed, stated resource allocation.

Run a strict local scorer

Download the scorer, the synthetic scheduling manifest, and the synthetic outcomes into one directory. Python 3.12 or newer and uv are sufficient. There are no model downloads, endpoint calls, or third-party Python dependencies.

score-synthetic-cohort.sh
1uv run score_requests.py example-trace.json example-events.jsonl > scored.json

Save the accounting tests beside those files and run uv run test_score_requests.py. They exercise timing, missing and duplicate outcomes, failure denominators, single-token output, malformed records, and CLI exit codes. Passing them checks the scorer, not a serving system.

The manifest fixes six IDs and scheduled times in [0, 2000) ms. Each JSONL outcome has this shape:

normalized-request-outcome.json
1{ 2 "id": "r01", 3 "sent_ms": 0, 4 "terminal_ms": 500, 5 "token_ms": [240, 280, 320, 440, 480], 6 "status": "success", 7 "quality_pass": true 8}

quality_pass is a supplied task judgment. The scorer doesn't judge semantics. Its input validation checks exact fields, finite nonnegative timestamps, temporal ordering, unique IDs, and a terminal outcome for every expected request. Unknown IDs, missing outcomes, duplicate JSON keys, nonfinite values, and empty successful outputs are errors. Equal token timestamps are allowed because the measuring clock can have finite resolution.

The supplied outcomes exercise different branches:

RequestOutcomeQualified?
r01TTFT 240 ms, TPOT 60 ms, terminal E2E 500 msYes
r02Single token, TTFT 170 ms; TPOT not applicableYes
r03TTFT 340 ms exceeds the 300 ms limitNo
r04TTFT 285 ms and TPOT 61 msYes
r05Fast successful response, but supplied quality judgment failsNo
r06Partial output followed by timeout at 2,500 msNo

All six count toward attainment, giving 3 / 6 = 50%. There are five protocol successes, not six. The cohort horizon is 2.5 seconds, giving 2.0 successful requests/s and 1.2 qualified requests/s. The arrival window is two seconds, giving a realized offered rate of 3.0 requests/s. These denominators are printed separately.

The report includes exact input hashes, per-request metrics, and successful-request-only percentile populations. Failed requests remain in attainment even though their partial streams don't enter successful-latency percentiles. capacity_estimate_rps is deliberately null: these records contain neither a sustained run nor a capacity sweep.

Exit code zero means the input and schedule checks passed, not that a deployment is approved. Code 2 means the accounting is available but a request was unsent or schedule lag exceeded 20 ms. Code 1 means malformed or incomplete inputs. Preserve nonzero exits in automation; don't let a successful tee hide them.

Try three changes in a copy of the JSONL file:

  1. Delete r06. The scorer must reject the incomplete cohort instead of improving attainment by dropping a timeout.
  2. Mark r05 as quality-passing. Attainment becomes four of six; the parser is trusting a changed judgment, not discovering better model quality.
  3. Change r04.sent_ms from 765 to 800. Its measured TTFT falls to 250 ms, but schedule lag rises to 40 ms and the run becomes invalid for its declared load.

For an unsent request, retain its ID with status not_sent, null sent_ms, no tokens, a terminal accounting time, and quality_pass: false. If the client retries requests, keep attempt-level records and a separate logical-request result; this small schema deliberately rejects duplicate IDs rather than silently merging retries.

Find a boundary without overstating the evidence

The hypothetical sweep below illustrates selection logic. The inputs are supplied observations, not results from the six-request parser fixture or any hardware run. Require 95% attainment, at most 20 ms schedule lag, and no sustained backlog growth.

Offered RPSQualified / offeredAttainmentMax schedule lagBacklog trendPoint estimate passes?
0.5200 / 200100%8 msflatYes
1.0200 / 200100%9 msflatYes
1.5190 / 20095%11 msflatYes
2.0160 / 20080%12 msgrowingNo
2.5116 / 20058%16 msgrowingNo

Under these arithmetic rules, 1.5 RPS is the highest passing tested point. It isn't a proven maximum between points, a statistically certified 95% service level, or a safe production target. Repeat and refine the boundary, test the failing neighbor, and select operating margin for failures and traffic drift.

Hypothetical request attainment falls from 100 percent at 0.5 and 1.0 offered requests per second to 95 percent at 1.5, 80 percent at 2.0, and 58 percent at 2.5. A horizontal 95 percent target identifies 1.5 as the highest passing supplied point, not a measured capacity result.
The 95% line separates passing point estimates from failures. The curve is illustrative; choosing capacity also requires schedule fidelity, stability, uncertainty, and repeated runs.

A percentile needs a population and enough observations

Nearest-rank p95 of 20 values selects the 19th ordered value. Nearest-rank p99 of 80 gaps selects the maximum. Those are reproducible calculations, not precise estimates of a production tail.

Pooled ITL percentiles give longer responses more weight because they contribute more gaps. A percentile across per-request worst gaps answers a different question. Neither can be recovered by averaging percentile summaries from separate runs. Keep raw samples, state the convention, and stratify meaningful prompt-length, output-length, and priority classes.

The same caution applies to attainment: observing 190 successes in 200 trials doesn't establish that the underlying pass probability is at least 95%. Predeclare an uncertainty rule and minimum evidence. For correlated traffic, resample whole runs or suitable time blocks rather than pretending each token gap is an independent sample. Repeating an unrepresentative trace can't repair its missing workload classes.

Alternate baseline and candidate run order. Keep cold-start and warm-capacity results separate, and consider a downward sweep when cache or thermal history creates hysteresis. Don't select the best of many noisy runs and omit the others.

Join performance and quality before release

Performance and quality need linked but distinct evidence. Check every performance response for protocol completion, finish reason, actual output length, and required schema. Use a stable task suite for factual support, correct tool arguments, abstention, and other semantic requirements.

A short answer produced by accidental truncation can look faster. A valid speculative decoder should preserve its target sampling distribution under its stated assumptions; “uses speculation” isn't itself evidence of degraded quality. Still verify the implemented combination, including stop handling and output parsing, rather than assuming that a faster engine preserved the task.

If semantic quality is evaluated only on a separate sampled suite, don't label every unscored performance request semantically qualified. Report performance attainment and the separate quality acceptance result. A per-request quality_pass field needs actual per-request evidence for that stronger claim.

Keep a compact record of:

  • Model, tokenizer, template, quantization, engine, client, and image identities.
  • Hardware count, placement, drivers, gateway/network scope, and relevant limits.
  • Exact workload bytes, realized timestamps, warmup/cache policy, timeouts, and run duration.
  • All terminal outcomes, raw timing events, quality judgments, and system telemetry.
  • Metric populations, denominators, thresholds, uncertainty rules, repetitions, and rejected runs.
  • Selected operating margin, recovery plan, and conditions that weren't tested.

A hash binds bytes, not truth. A successful parser proves that records satisfy its schema and arithmetic rules, not that they were collected faithfully. Preserve original logs and measurement provenance so another engineer can inspect that boundary.

The report shows good attainment, flat queue depth, and exit code zero. Can you approve the serving configuration from that alone?

Answer

No. Check whether the load was reproduced, failures and rejections were retained, the workload and quality evidence are representative, and the run is long and repeatable enough to support the claim. The local scorer intentionally doesn't infer capacity or approve a deployment.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.A fixed-concurrency client slows its arrivals when the server slows. Which test better measures capacity under an external arrival rate?

Correct answer: Replay a fixed schedule and measure whether sends keep up.

An independent schedule preserves offered pressure. Measuring send lag checks whether the client actually delivered that schedule.

2.A request is sent at 0 ms, its last token arrives at 480 ms, and its terminal event arrives at 500 ms. What is terminal E2E latency?

Correct answer: 500 ms, using the declared terminal boundary.

The last-token and terminal-completion boundaries differ by 20 ms. Report the boundary you actually measured.

3.Token times after sending are 240, 280, 320, 440, and 480 ms. What are TTFT and mean TPOT?

Correct answer: TTFT 240 ms; TPOT 60 ms.

There are four decode intervals spanning 240 ms, so their mean is 60 ms. The 120 ms gap remains relevant despite that mean.

4.Six offered requests produce three qualified responses, two other successful responses, and one timeout. What is request attainment?

Correct answer: 50%, retaining all six offered requests in the denominator.

Qualified work is three of six. Dropping the timeout or counting fast wrong answers would change the stated contract.

5.A successful single-token response has no inter-token intervals. How should an evaluator represent TPOT when the decode criterion is declared not applicable?

Correct answer: It records null TPOT and omits it from decode percentiles.

There is no interval to average. TTFT, quality, and terminal success still determine whether the request qualifies.

6.A client receives chunks containing several tokens. What can it report without inventing token arrival times?

Correct answer: Inter-chunk latency with the observed boundaries stated.

Chunk timing is real evidence, but it doesn't reveal how individual tokens were emitted inside the chunk.

7.A request scheduled at 760 ms is sent at 800 ms, exceeding a 20 ms schedule-lag budget. Its send-relative TTFT passes. What follows?

Correct answer: The accounting can be reported, but this run fails schedule fidelity.

The 40 ms lag means the intended load wasn't delivered within tolerance. A good response after the delayed send doesn't fix that.

8.A synthetic sweep passes the point-estimate rules at 1.5 RPS and fails at 2.0 RPS. What is justified?

Correct answer: 1.5 RPS is the highest passing supplied point, not measured capacity.

Supplied observations illustrate selection rules. Real capacity needs a reproduced workload, stability evidence, repeated measurements, and uncertainty analysis.

9.Why shouldn't a reviewer average p99 ITL values from several runs and call the result pooled p99?

Correct answer: A percentile of a combined distribution isn't the mean of its percentiles.

Retain the samples or use an appropriate mergeable distribution summary. Also state whether the population weights token gaps or requests.

9 questions remaining.

Next Step
Continue to A/B Testing for LLMs

Test whether a serving or model change improves real user outcomes, with stable assignment, statistical uncertainty, and live guardrails.

PreviousDistributed Inference Data Plane
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

BurstGPT: A Real-World Workload Dataset to Optimize LLM Serving Systems

Wang, Y., Chen, Y., Li, Z., et al. · 2025 · arXiv preprint

https://arxiv.org/abs/2401.17644

ServeGen: Workload Characterization and Generation of Large Language Model Serving in Production

Xiang, Y., Li, X., Qian, K., Zhang, Y., Yu, W., Zhai, E., Jin, X., and Zhou, J. · 2026 · NSDI 2026

https://www.usenix.org/conference/nsdi26/presentation/xiang-servegen

MLPerf Inference Benchmark Rules.

MLCommons · 2026 · Official benchmark rules

https://github.com/mlcommons/inference_policies/blob/master/inference_rules.adoc

A Proof for the Queuing Formula: L = lambda W

Little, J. D. C. · 1961 · Operations Research

https://doi.org/10.1287/opre.9.3.383

Benchmark CLI

vLLM Project · 2026 · Official vLLM documentation

https://docs.vllm.ai/en/stable/benchmarking/cli/

Etalon: Holistic Performance Evaluation Framework for LLM Inference Systems.

Agrawal, A., et al. · 2024 · arXiv preprint

https://arxiv.org/abs/2407.07000

DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving.

Zhong, Y., et al. · 2024 · OSDI 2024

https://arxiv.org/abs/2401.09670

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.