inferlint

vLLM 0.28 on an RTX 4090

vLLM 0.28.0 · Qwen3.8-27B-W4A16-AutoRound · 26,093-token KV pool · concurrency asked for: 32

What happened

The load tool kept 32 requests open for 1 min 34 s. The server finished 32 requests with no errors and generated 32,000 tokens. It never worked on more than 10 at once. The rest waited in a queue, 29 s on average before a request started. It preempted a running request 22 times to free KV cache: each one went back to the queue and later recomputed its prompt and output so far. The server log does not mention this.

Ran at onceTripwire failed
10 of 32
The load tool kept 32 requests open.
PreemptionsTripwire failed
22
Requests evicted and recomputed. The server log mentions none.
Output tokens per second
341.4
over 93.7 s; a whole-second timer reads +0.77%
Usable KV blocks
42
43 reported, one held back; 784 tokens per block

The test

Measured time
1 min 34 s (93.7 s), from the before to the after reading
Clock time
2026-09-26 17:50:52 to 17:52:25 (UTC-7)
Server start-up
2 min 4 s, before the test (from the boot log)
Requests finished
32: 32 reached their token limit, no errors
Output tokens generated
32,000 (1,000 per request)
Prompt tokens read
2,819 (88 per request)
Average time per request
54.4 s
Average wait for the first token
29.6 s, 29.3 s of it waiting in the queue

The setup

Concurrency asked for
32 requests at once
Requests sent by
the load tool. inferlint sends none: it only reads the server's counters.
Recording
the server read every 0.25 s, 365 readings
Server address
http://127.0.0.1:8000
Made from
boot.log, before.snapshot.json, after.snapshot.json, run.series.jsonl
Tripwires checked
8 of 15. Not here: T2 and T3 (run at clean-up), T4 and T11 (need two or more boot logs), T7 (needs a live server), T13 (a rule for test scripts), T15 (needs the load tool's result file)
Words used in this report
Token
The unit of text a model reads and writes, defined by its tokenizer. How much text one token covers depends on the model, the tokenizer and the language. Throughput, KV cache and cost are all counted in tokens.
Prompt and output tokens
Prompt tokens are the input sent to the model. Output tokens are the tokens it generates in reply.
Request
One completion request sent to the server, and its response.
Concurrency
The number of requests in progress at the same moment. 'Asked for' is how many the load tool kept open. 'Running' is how many the scheduler was actually processing. The rest wait in its queue.
Waiting (queue)
Requests the server has accepted but not scheduled, because the KV cache has no room for them yet.
KV cache
GPU memory holding the attention keys and values for every token of every running request, so they are not recomputed for each new token. A request's KV grows with its length.
KV pool
The size of the KV cache in tokens, set when vLLM starts from the GPU memory left after the model and CUDA graphs are loaded. It can differ from one start to the next (T4, T11).
KV block
The allocation unit of the KV cache: a request always holds whole blocks, so even a short request holds a full one. The usual size is 16 tokens; models that mix attention and Mamba layers use blocks of hundreds of tokens (T5).
Null block
One block vLLM reserves and never gives to a request, so a pool of N blocks holds requests in N - 1 of them (T14).
Fit in cache (ceiling)
How many requests of their current size fit when the cache is full: floor(1 / share), where share is the fraction of the cache one request holds. As sequences grow, fewer fit (T9).
Preemption
When a running request needs a block and none is free, vLLM evicts a running request: it frees that request's KV blocks and later recomputes them from the prompt and the output so far. vLLM counts it in vllm:num_preemptions_total and writes no log line (T1).
Output tokens per second
Tokens generated per second by all requests together, from the server's own counter.
Time to first token
Time from sending a request until the first token of the answer comes back. It includes the time spent waiting in the queue.
Boot log
The messages vLLM prints while it starts. They record the settings it actually chose, which can differ from the ones asked for.
Before and after readings
Copies of the server's counters taken just before and just after the test. The difference between them is what happened during the test.
Recording
The server's gauges, read several times a second during the test. The charts are drawn from it.
Attention backend
The code that does the model's main calculation on the GPU. vLLM has several and picks one unless it is told which (T6).
CUDA graphs
A speed-up in which vLLM records the GPU's steps once at start-up and replays them. It costs a little memory.

Results

The server worked; the failed tripwires are about the measurement. Some numbers from this run cannot be taken at face value. The server finished 32 requests with no errors.

What Pass, Warning, Tripwire failed and Can't tell mean
ResultWhat it meansWhat to do
Tripwire failedThe tripwire caught its problem in this run. For T7 and T12 that means the server failed. For every other tripwire the server worked, but a number from the run (concurrency, throughput or latency) does not mean what it seems.Read the finding. Fix the setup and run again, or report the number together with the finding.
WarningNothing is wrong on its own, but a setting or an effect changes how the numbers should be read.Keep the warning with the results, so whoever compares them knows.
Can't tellThe check could not decide, because a counter or log line it needs was missing, for example from a vLLM version it does not know. It never counts as a pass.Supply the missing file, or check the vLLM version.
PassThe tripwire looked for its problem in this run and did not find it.Nothing. A pass covers this run only.
  1. Tripwire failed
    T1Silent preemption

    22 preemptions during the run

    A preempted request waits in the queue again and repeats work, so latency and throughput include recomputation the client never sees. Searching the server log finds nothing.

  2. Tripwire failed
    T8Concurrency not reached

    requested 32 concurrent, server never ran more than 10

    A result labelled 'concurrency 32' can describe a server that never ran more than 10 requests at once.

  3. Warning
    T5Large KV block size

    attention block size forced to 784 tokens (requested 16); each request's KV is allocated in 784-token units

    Every request holds whole blocks, so a short request occupies a full block and far fewer requests fit than the pool's token count suggests.

  4. Warning
    T9Concurrency ceiling falls as sequences grow

    ceiling moved between 7 and 10 as requests grew (one request held 9.5% to 14.3% of the cache); concurrency was not a constant of this run

    A run has no single maximum concurrency, so one figure for it describes none of the run.

  5. Pass
    T6Requested attention backend ignored

    nothing to check: the server was started without --attention-backend, so vLLM chose its own (FLASH_ATTN) and nothing could be ignored; there was no draft model either

  6. Pass
    T10Integer-second timing

    341.44 tokens/s over 93.720s

  7. Pass
    T12Start-up failure without a cause

    no failure in log

  8. Pass
    T14Reserved null block

    gauge denominator is 42 = num_gpu_blocks (43) - 1 null block

What the server did

Requests over time

Requests the server was working on, requests queued behind them, and how many requests of their current size fit in the cache when it is full. Triangles mark preemptions.

  • running
  • waiting
  • how many fit in the cache
  • concurrency asked for
  • preemption
010203040020406080sasked for 324 preemptions at 16.2 s1 preemption at 16.7 s1 preemption at 17.2 s1 preemption at 17.5 s1 preemption at 24.4 s1 preemption at 24.7 s1 preemption at 40.6 s3 preemptions at 40.9 s1 preemption at 41.4 s2 preemptions at 48.3 s1 preemption at 49.3 s1 preemption at 56.0 s3 preemptions at 65.0 s1 preemption at 72.1 s
Data table
secondsrunningwaitingfit in cache
0.0000–
0.26102210
0.51102210
0.77102210
1.03102210
1.28102210
1.54102210
1.80102210
2.05102210
2.31102210
2.57102210
2.83102210
3.08102210
3.34102210
3.59102210
3.85102210
4.11102210
4.36102210
4.62102210
4.88102210
5.13102210
5.39102210
5.65102210
5.90102210
6.16102210
6.42102210
6.67102210
6.93102210
7.19102210
7.45102210
7.71102210
7.97102210
8.23102210
8.48102210
8.74102210
9.00102210
9.25102210
9.51102210
9.77102210
10.02102210
10.28102210
10.54102210
10.79102210
11.05102210
11.31102210
11.56102210
11.82102210
12.08102210
12.34102210
12.62102210
12.87102210
13.13102210
13.39102210
13.64102210
13.90102210
14.15102210
14.41102210
14.67102210
14.92102210
15.18102210
15.44102210
15.70102210
15.95102210
16.21626–
16.478248
16.72626–
16.987257
17.248248
17.498248
17.75725–
18.01725–
18.26725–
18.52725–
18.77725–
19.03725–
19.29725–
19.55725–
19.80725–
20.06725–
20.32725–
20.57725–
20.83725–
21.09725–
21.34725–
21.60725–
21.86725–
22.11725–
22.37725–
22.63725–
22.88725–
23.14725–
23.40725–
23.65725–
23.91725–
24.17224–
24.429179
24.68718–
24.949169
25.199169
25.459169
25.719169
25.969169
26.229169
26.489169
26.749169
26.999169
27.259169
27.509169
27.769169
28.029169
28.279169
28.539169
28.799169
29.049169
29.309169
29.569169
29.819169
30.079169
30.349169
30.599169
30.859169
31.119169
31.379169
31.63914–
31.89101210
32.14101210
32.40101210
32.65101210
32.91101210
33.17101210
33.42101210
33.68101210
33.94101210
34.19101210
34.45101210
34.71101210
34.96101210
35.22101210
35.47101210
35.73101210
35.99101210
36.24101210
36.50101210
36.76101210
37.01101210
37.27101210
37.52101210
37.78101210
38.04101210
38.29101210
38.55101210
38.81101210
39.06101210
39.32101210
39.57101210
39.83101210
40.09101210
40.34101210
40.609139
40.867157
41.119139
41.379139
41.629139
41.889139
42.149139
42.409139
42.659139
42.919139
43.169139
43.429139
43.689139
43.939139
44.199139
44.449139
44.709139
44.969139
45.219139
45.479139
45.749139
45.999139
46.259139
46.519139
46.769139
47.029139
47.279139
47.539139
47.799139
48.049139
48.30315–
48.56512–
48.81512–
49.0710610
49.33979
49.58979
49.84979
50.09979
50.35979
50.61979
50.86979
51.12979
51.38979
51.63979
51.89979
52.15979
52.40979
52.66979
52.92979
53.17979
53.43979
53.68979
53.94979
54.20979
54.45979
54.71979
54.97979
55.22979
55.48979
55.7487–
55.99959
56.2510310
56.5110310
56.7710310
57.0310310
57.2810310
57.5410310
57.8010310
58.0510310
58.3110310
58.5610310
58.8210310
59.0810310
59.3310310
59.5910310
59.8410310
60.1010310
60.3610310
60.6110310
60.8710310
61.1310310
61.3810310
61.6410310
61.8910310
62.1510310
62.4110310
62.6610310
62.9210310
63.1810210
63.4310210
63.6910210
63.9510210
64.2010210
64.4610210
64.7110210
64.97757
65.23939
65.48939
65.74939
66.00939
66.25939
66.51939
66.76939
67.02939
67.28939
67.53939
67.79939
68.05939
68.30939
68.56939
68.81939
69.07939
69.33939
69.58939
69.84939
70.09939
70.35939
70.61939
70.86939
71.12939
71.37939
71.63939
71.89939
72.1444–
72.4080–
72.6670–
72.9170–
73.1770–
73.4370–
73.6870–
73.9470–
74.2070–
74.4570–
74.7170–
74.9770–
75.2270–
75.4870–
75.7370–
75.9970–
76.2570–
76.5070–
76.7670–
77.0270–
77.2770–
77.5370–
77.7870–
78.0470–
78.3070–
78.5570–
78.8170–
79.0650–
79.3230–
79.5830–
79.8330–
80.0930–
80.3430–
80.6030–
80.8630–
81.1130–
81.3730–
81.6230–
81.8830–
82.1430–
82.3930–
82.6530–
82.9130–
83.1630–
83.4230–
83.6730–
83.9330–
84.1930–
84.4430–
84.7030–
84.9630–
85.2130–
85.4730–
85.7330–
85.9830–
86.2430–
86.4930–
86.7530–
87.0130–
87.2630–
87.5230–
87.7830–
88.0330–
88.2930–
88.5530–
88.8030–
89.0630–
89.3130–
89.5730–
89.8330–
90.0830–
90.3430–
90.6030–
90.8530–
91.1130–
91.3730–
91.6230–
91.8820–
92.1420–
92.4020–
92.6520–
92.9120–
93.1720–
93.4220–

KV cache in use

Share of the cache holding requests. The gauge moves in steps of 1/42: one block is held back (T14).

  • preemption
0%25%50%75%100%020406080s4 preemptions at 16.2 s1 preemption at 16.7 s1 preemption at 17.2 s1 preemption at 17.5 s1 preemption at 24.4 s1 preemption at 24.7 s1 preemption at 40.6 s3 preemptions at 40.9 s1 preemption at 41.4 s2 preemptions at 48.3 s1 preemption at 49.3 s1 preemption at 56.0 s3 preemptions at 65.0 s1 preemption at 72.1 s
Data table
seconds% in use
0.000.0
0.2695.2
0.5195.2
0.7795.2
1.0395.2
1.2895.2
1.5495.2
1.8095.2
2.0595.2
2.3195.2
2.5795.2
2.8395.2
3.0895.2
3.3495.2
3.5995.2
3.8595.2
4.1195.2
4.3695.2
4.6295.2
4.8895.2
5.1395.2
5.3995.2
5.6595.2
5.9095.2
6.1695.2
6.4295.2
6.6795.2
6.9395.2
7.1995.2
7.4595.2
7.7195.2
7.9795.2
8.2395.2
8.4895.2
8.7495.2
9.0095.2
9.2595.2
9.5195.2
9.7795.2
10.0295.2
10.2895.2
10.5495.2
10.7995.2
11.0595.2
11.3195.2
11.5695.2
11.8295.2
12.0895.2
12.3495.2
12.6295.2
12.8795.2
13.1395.2
13.3995.2
13.6495.2
13.9095.2
14.1595.2
14.4195.2
14.6795.2
14.9295.2
15.1895.2
15.4495.2
15.7095.2
15.9595.2
16.2185.7
16.47100.0
16.7283.3
16.9897.6
17.24100.0
17.4992.9
17.7583.3
18.0183.3
18.2683.3
18.5283.3
18.7783.3
19.0383.3
19.2983.3
19.5583.3
19.8083.3
20.0683.3
20.3283.3
20.5783.3
20.8383.3
21.0983.3
21.3483.3
21.6083.3
21.8683.3
22.1183.3
22.3783.3
22.6383.3
22.8883.3
23.1483.3
23.4083.3
23.6583.3
23.9183.3
24.1731.0
24.4297.6
24.6881.0
24.9492.9
25.1992.9
25.4592.9
25.7192.9
25.9692.9
26.2292.9
26.4892.9
26.7492.9
26.9992.9
27.2592.9
27.5092.9
27.7692.9
28.0292.9
28.2792.9
28.5392.9
28.7992.9
29.0492.9
29.3092.9
29.5692.9
29.8192.9
30.0792.9
30.3492.9
30.5992.9
30.8592.9
31.1192.9
31.3792.9
31.6388.1
31.8995.2
32.1495.2
32.4095.2
32.6595.2
32.9195.2
33.1795.2
33.4295.2
33.6895.2
33.9495.2
34.1995.2
34.4595.2
34.7195.2
34.9695.2
35.2295.2
35.4795.2
35.7395.2
35.9995.2
36.2495.2
36.5095.2
36.7695.2
37.0195.2
37.2795.2
37.5295.2
37.7895.2
38.0495.2
38.2995.2
38.5595.2
38.8195.2
39.0695.2
39.3295.2
39.5795.2
39.8395.2
40.0995.2
40.3495.2
40.6095.2
40.8692.9
41.1197.6
41.37100.0
41.62100.0
41.88100.0
42.14100.0
42.40100.0
42.65100.0
42.91100.0
43.16100.0
43.42100.0
43.68100.0
43.93100.0
44.19100.0
44.44100.0
44.70100.0
44.96100.0
45.21100.0
45.47100.0
45.74100.0
45.99100.0
46.25100.0
46.51100.0
46.76100.0
47.02100.0
47.27100.0
47.53100.0
47.79100.0
48.04100.0
48.3042.9
48.5652.4
48.8152.4
49.07100.0
49.3392.9
49.5892.9
49.8492.9
50.0992.9
50.3592.9
50.6192.9
50.8692.9
51.1292.9
51.3892.9
51.6392.9
51.8992.9
52.1592.9
52.4092.9
52.6692.9
52.9292.9
53.1792.9
53.4392.9
53.6892.9
53.9492.9
54.2092.9
54.4592.9
54.7192.9
54.9792.9
55.2292.9
55.4892.9
55.7481.0
55.9997.6
56.2597.6
56.5197.6
56.7797.6
57.0397.6
57.2897.6
57.5497.6
57.8097.6
58.0597.6
58.3197.6
58.5697.6
58.8297.6
59.0897.6
59.3397.6
59.5997.6
59.8497.6
60.1097.6
60.3697.6
60.6197.6
60.8797.6
61.1397.6
61.3897.6
61.6497.6
61.8997.6
62.1597.6
62.4197.6
62.6697.6
62.9297.6
63.1895.2
63.4395.2
63.6995.2
63.9595.2
64.2095.2
64.4695.2
64.7195.2
64.97100.0
65.2397.6
65.4897.6
65.7497.6
66.0097.6
66.2597.6
66.5197.6
66.7697.6
67.0297.6
67.2897.6
67.5397.6
67.7997.6
68.0597.6
68.3097.6
68.5697.6
68.8197.6
69.0797.6
69.3397.6
69.5897.6
69.8497.6
70.0997.6
70.3597.6
70.6197.6
70.8697.6
71.1297.6
71.3797.6
71.6397.6
71.8997.6
72.1452.4
72.4083.3
72.6673.8
72.9176.2
73.1776.2
73.4376.2
73.6876.2
73.9476.2
74.2076.2
74.4576.2
74.7176.2
74.9776.2
75.2276.2
75.4876.2
75.7376.2
75.9976.2
76.2576.2
76.5076.2
76.7676.2
77.0276.2
77.2776.2
77.5376.2
77.7876.2
78.0476.2
78.3076.2
78.5576.2
78.8176.2
79.0652.4
79.3228.6
79.5828.6
79.8328.6
80.0928.6
80.3428.6
80.6028.6
80.8628.6
81.1128.6
81.3728.6
81.6228.6
81.8828.6
82.1428.6
82.3928.6
82.6528.6
82.9128.6
83.1628.6
83.4228.6
83.6728.6
83.9328.6
84.1928.6
84.4428.6
84.7028.6
84.9628.6
85.2128.6
85.4738.1
85.7331.0
85.9831.0
86.2431.0
86.4931.0
86.7531.0
87.0131.0
87.2635.7
87.5235.7
87.7835.7
88.0335.7
88.2935.7
88.5535.7
88.8035.7
89.0635.7
89.3135.7
89.5735.7
89.8335.7
90.0835.7
90.3435.7
90.6035.7
90.8535.7
91.1135.7
91.3735.7
91.6235.7
91.8823.8
92.1423.8
92.4023.8
92.6523.8
92.9123.8
93.1723.8
93.4223.8

Output tokens per second

Generated tokens over a sliding one-second window, from the server's own counter.

0200400600020406080s
Data table
secondstokens/s
0.00–
0.263.9
0.51215.9
0.77286.7
1.03441.6
1.28442.0
1.54442.3
1.80442.6
2.05442.6
2.31442.3
2.57440.9
2.83439.4
3.08439.5
3.34440.9
3.59442.0
3.85442.1
4.11442.4
4.36442.7
4.62442.2
4.88441.2
5.13441.0
5.39441.2
5.65428.9
5.90442.0
6.16442.1
6.42442.2
6.67442.0
6.93439.9
7.19437.1
7.45437.3
7.71438.5
7.97436.9
8.23436.8
8.48437.6
8.74442.0
9.00428.9
9.25441.8
9.51442.1
9.77442.1
10.02428.5
10.28428.4
10.54441.8
10.79442.4
11.05442.4
11.31428.7
11.56440.9
11.82440.9
12.08441.5
12.34427.6
12.62426.7
12.87439.2
13.13441.0
13.39442.3
13.64429.7
13.90429.7
14.15429.6
14.41429.4
14.67429.2
14.92441.1
15.18441.1
15.44440.3
15.70427.2
15.95427.3
16.21399.4
16.47265.0
16.72131.2
16.9832.5
17.2433.8
17.4954.6
17.75120.9
18.01221.1
18.26300.6
18.52327.8
18.77327.5
19.03326.5
19.29325.9
19.55326.3
19.80327.1
20.06318.3
20.32318.2
20.57318.5
20.83327.7
21.09327.5
21.34318.4
21.60318.4
21.86318.2
22.11327.2
22.37327.4
22.63318.6
22.88317.6
23.14316.9
23.40326.2
23.65327.3
23.91328.0
24.17235.4
24.42128.6
24.6853.3
24.94139.0
25.19265.1
25.45360.0
25.71397.8
25.96398.0
26.22408.4
26.48395.7
26.74407.3
26.99397.1
27.25410.0
27.50398.3
27.76398.2
28.02398.0
28.27398.1
28.53410.0
28.79397.6
29.04408.7
29.30396.9
29.56397.7
29.81397.9
30.07397.8
30.34403.1
30.59391.2
30.85402.3
31.11394.5
31.37404.0
31.63350.4
31.89325.5
32.14343.5
32.40401.0
32.65442.6
32.91442.4
33.17442.5
33.42442.9
33.68442.0
33.94441.9
34.19441.8
34.45429.8
34.71442.1
34.96441.9
35.22442.1
35.47442.8
35.73442.6
35.99442.4
36.24429.0
36.50441.7
36.76441.7
37.01442.1
37.27429.6
37.52429.3
37.78442.0
38.04442.1
38.29442.3
38.55429.4
38.81442.3
39.06442.4
39.32442.7
39.57429.5
39.83428.9
40.09441.5
40.34441.9
40.60441.2
40.86315.1
41.11180.9
41.3783.2
41.62181.9
41.88301.5
42.14397.6
42.40396.6
42.65396.7
42.91396.9
43.16398.3
43.42398.1
43.68398.2
43.93398.4
44.19398.6
44.44387.0
44.70398.6
44.96398.5
45.21398.3
45.47395.6
45.74393.1
45.99403.8
46.25394.8
46.51397.3
46.76386.6
47.02397.8
47.27397.7
47.53397.6
47.79386.3
48.04397.8
48.30291.1
48.56166.4
48.8126.0
49.0768.9
49.33206.9
49.58335.7
49.84410.9
50.09397.8
50.35397.7
50.61397.6
50.86397.6
51.12409.6
51.38398.1
51.63409.6
51.89397.5
52.15397.2
52.40397.2
52.66397.6
52.92410.0
53.17398.4
53.43398.3
53.68398.1
53.94397.7
54.20409.4
54.45397.6
54.71397.7
54.97397.4
55.22397.7
55.48397.4
55.74373.8
55.99343.3
56.25341.1
56.51366.7
56.77410.2
57.03440.3
57.28441.3
57.54442.2
57.80429.2
58.05442.0
58.31442.3
58.56442.6
58.82429.7
59.08442.2
59.33442.0
59.59442.4
59.84429.5
60.10442.5
60.36442.6
60.61442.9
60.87429.6
61.13429.3
61.38441.9
61.64442.1
61.89442.1
62.15429.2
62.41429.1
62.66441.8
62.92441.4
63.18427.4
63.43415.1
63.69415.6
63.95429.5
64.20441.9
64.46442.0
64.71442.0
64.97422.5
65.23297.6
65.48248.1
65.74252.0
66.00362.7
66.25398.4
66.51398.5
66.76398.2
67.02398.2
67.28398.3
67.53398.2
67.79398.1
68.05386.3
68.30397.9
68.56397.9
68.81398.1
69.07398.4
69.33398.6
69.58398.6
69.84386.8
70.09398.4
70.35398.5
70.61398.6
70.86386.9
71.12398.2
71.37398.1
71.63397.9
71.89386.1
72.14370.3
72.40246.9
72.66193.4
72.91189.6
73.17293.3
73.43327.5
73.68327.3
73.94327.3
74.20327.3
74.45327.7
74.71328.2
74.97328.1
75.22328.2
75.48327.9
75.73327.5
75.99327.5
76.25327.7
76.50328.1
76.76328.1
77.02318.7
77.27318.6
77.53318.4
77.78327.7
78.04327.8
78.30328.0
78.55328.0
78.81328.2
79.06306.1
79.32260.6
79.58197.9
79.83161.4
80.09144.5
80.34144.5
80.60144.5
80.86144.5
81.11148.4
81.37144.5
81.62144.6
81.88144.6
82.14144.6
82.39144.6
82.65144.4
82.91144.2
83.16144.0
83.42144.1
83.67144.4
83.93144.5
84.19144.4
84.44144.4
84.70144.3
84.96144.3
85.21144.4
85.47144.3
85.73144.3
85.98144.3
86.24144.4
86.49144.3
86.75144.3
87.01144.4
87.26144.4
87.52144.4
87.78144.4
88.03140.4
88.29144.2
88.55144.3
88.80144.3
89.06144.5
89.31144.5
89.57144.4
89.83144.3
90.08144.2
90.34144.4
90.60144.5
90.85144.5
91.11143.8
91.37143.5
91.62143.6
91.88135.1
92.14118.2
92.40104.7
92.6598.3
92.9198.4
93.1798.9
93.4298.8

How many requests ran at once, and for how long

Each bar is the total time the server spent working on exactly that many requests at the same time. The load tool asked for 32 the whole time, but the server never ran more than 10.

010203040seconds10 at once33.69 at once28.28 at once1.37 at once13.86 at once0.55 at once0.84 at once0.33 at once12.82 at once1.8
Data table
running at onceseconds
1033.64
928.24
81.28
713.85
60.51
50.77
40.26
312.82
21.80

The server that ran

From boot.log. Every result should carry these, because they change from one start to the next.

vLLM
0.28.0
Model
Qwen3.8-27B-W4A16-AutoRound
KV pool
26,093 tokens
Attention block
784 tokens
Attention backend
FLASH_ATTN
Draft model backend
none
Memory for KV cache
2.09 GiB
CUDA graphs
on, 0.18 GiB
Boot line 'maximum concurrency'
1.59x at 16,384 tokens
Model load
17.71 GiB in 79 s
Server settings
gpu_memory_utilization=0.93, host=127.0.0.1, max_model_len=16384, max_num_seqs=32, served_model_name=['qwen38']

The 15 tripwires

Each one is a way an inference benchmark can report a wrong number without raising an error.

  1. T1Silent preemptionsilent-preemption

    When the KV cache has no free block for a running request, vLLM preempts a request: it frees that request's KV blocks and later recomputes them from the prompt and the output so far. vLLM increments vllm:num_preemptions_total and writes no log line at the default log level (verified on vLLM 0.28, 0.29 and 0.30).

    A preempted request waits in the queue again and repeats work, so latency and throughput include recomputation the client never sees. Searching the server log finds nothing.

    inferlint preemption before.json after.json
  2. T2Orphaned engine processorphaned-engine

    pkill -f "vllm serve" matches only the API-server process. The engine process, which holds the weights and the KV cache in GPU memory, renames itself VLLM::EngineCore and can outlive its parent when the parent is killed.

    The next server starts in whatever GPU memory is left and sizes a smaller KV pool, with no error. One low memory reading is not proof the GPU is free, so inferlint waits for two in a row.

    inferlint teardown | inferlint gpu-inspect
  3. T3Cleanup kills its own shellcleanup-self-kill

    pkill -f "vllm serve" inside a bash -c one-liner also matches that shell, because the shell's own command line contains the pattern.

    The shell is killed before the rest of the cleanup runs, and the script ends without an error message.

    inferlint teardown
  4. T4KV pool size jumps between startspool-size-jump

    vLLM sizes the KV pool at each start from the GPU memory left after loading the model and capturing CUDA graphs, and the pool comes in discrete steps. Starts with identical flags can land on different steps; T11 is the cause.

    Two runs with the same flags can differ by a whole step (9.4% in the recorded example), which reads as a performance difference and is not one.

    inferlint check-log boot1.log boot2.log
  5. T5Large KV block sizelarge-kv-blocks

    For hybrid attention/Mamba models, vLLM raises the attention block size (the KV cache allocation unit) from 16 tokens to hundreds, so that attention pages and Mamba state pages line up.

    Every request holds whole blocks, so a short request occupies a full block and far fewer requests fit than the pool's token count suggests.

    inferlint check-log boot.log
  6. T6Requested attention backend ignoredbackend-ignored

    --attention-backend sets the target model's attention backend. With speculative decoding, the draft model selects its own backend from a candidate list and does not apply the flag.

    In the recorded case Triton was requested and logged for the target model, but the draft model selected FlashInfer, which failed on the first request.

    inferlint check-log boot.log
  7. T7Crash after readycrash-after-ready

    A server can log 'Application startup complete' and then fail on its first request, when a code path start-up never ran is reached (for example a kernel compiled on first use).

    A gate that only waits for readiness passes a server that cannot serve. inferlint probe sends real requests; inferlint check-log reports T7 when the log shows a failure after ready.

    inferlint probe http://127.0.0.1:8000
  8. T8Concurrency not reachedconcurrency-not-reached

    A load tool's concurrency is the number of requests it keeps open. vllm:num_requests_running is the number the scheduler actually runs; the rest wait in its queue. Admission-control limits (--max-num-queued-reqs, --max-num-queued-tokens, vLLM 0.29 and later) can also reject requests.

    A result labelled 'concurrency 32' can describe a server that never ran more than 10 requests at once.

    inferlint series run.series.jsonl --requested 32
  9. T9Concurrency ceiling falls as sequences growfalling-ceiling

    With the KV cache full, the number of requests that fit is floor(1 / share), where share is the fraction of the cache one running request holds. The share grows with sequence length, so the ceiling falls during a run, and each fall preempts requests (T1).

    A run has no single maximum concurrency, so one figure for it describes none of the run.

    inferlint series run.series.jsonl
  10. T10Integer-second timinginteger-second-timer

    Timing a run with whole seconds, such as $(date +%s), is off by up to one second at each end.

    On a 30-second run that is about 3%, enough to reverse a close comparison. inferlint uses the sub-second clocks recorded with each snapshot.

    inferlint rate before.json after.json
  11. T11KV memory budget drifts between startskv-memory-drift

    The 'Available KV cache memory' vLLM reports at start-up can differ between starts with identical flags, mostly because CUDA-graph capture memory varies.

    A small drift can move the KV pool to a different step (T4). Record the per-start figure with every result.

    inferlint check-log boot1.log boot2.log
  12. T12Start-up failure without a causeunexplained-failure

    When a server fails to start, a search of the log for 'Error' usually finds a wrapper line rather than the root cause, and the failure is recorded with no reason.

    A failure without its cause cannot be fixed, reproduced or compared.

    inferlint check-log boot.log
  13. T13Stale waiter adopts the next serverstale-waiter

    A test script stopped while it waits for its server to become ready can leave its wait loop running. That loop sees the next script's server come up, reports it as its own, and later shuts it down.

    The next test dies partway through with no visible cause.

    see docs/orchestration.md
  14. T14Reserved null blocknull-block

    vLLM exports num_gpu_blocks = N but reserves one block (the null block), and vllm:kv_cache_usage_perc counts out of N - 1 (verified on vLLM 0.28, 0.29 and 0.30).

    Capacity computed from the exported block count is one block too high.

    inferlint series run.series.jsonl --snapshot after.json
  15. T15Client and server counts disagreeclient-server-mismatch

    The load tool's own counts for the run (requests completed, output tokens) are compared with the server's counters between the before and after snapshots.

    If the server did more work than the load tool sent, other traffic shared the server and the result is contaminated. If it did less, the load tool counted work the server did not do.

    inferlint xray -o results/ -- vllm bench serve ...