4.3

Keep CUDA graphs and compile on

The default compile level is the right one for most servers, and eager mode costs a few percent of decode speed.

Startup takes minutes and you want it faster. When you finish this section, you can decide what each compile level and eager mode cost.

Our result: on our L4, eager mode cost about 2 percent of the time per token in a cooled run. In a throttled run, -O0 cost about 2 percent for one user, and -O3 matched the default.

Know the switches

vLLM sets compile and CUDA graphs with one level, from -O0 to -O3. The default is -O2. The compile page explains what each part does.

SettingCompileCUDA graphsUse it for
-O2, the defaultonfull and piecewiseproduction
-O3the same as -O2 in 0.31.0nothing extra yet
-O1on, with fewer fusionspiecewise onlya faster start that keeps compile and graphs on, not measured by us
-O0offoffa fast start when you test a change
--enforce-eageroffoffdebugging a kernel, because it also skips the kernel warmup

Read what the start costs

The startup log gives the time of each part. On our DGX Spark, with Qwen3-30B-A3B, the two graph captures and the compile took about 96 seconds of a start of about eight minutes:

graph capture and compile time at startuptextFull log
(EngineCore pid=143) INFO 10-21 10:59:45 [model_runner.py:1087] Graph capturing finished in 39 secs, took 1.17 GiB
(EngineCore pid=143) INFO 10-21 11:00:51 [model_runner.py:1087] Graph capturing finished in 38 secs, took 0.31 GiB
(EngineCore pid=143) INFO 10-21 11:00:53 [core.py:373] init engine (profile, create kv cache, warmup model) took 127.54 s (compilation: 18.67 s)
The first two lines are the two capture passes. The last line gives the whole engine start and the compile share.

On that start, loading the weights took about 330 seconds, much more than the compile. A later start can read the compile cache, so the compile share gets smaller.

See what our runs show

We measured eager mode against the default on the L4 with Qwen/Qwen3-8B on 2026-10-21, in the full-clock session. Both runs used the same pool, seven concurrencies, and three seeds, with the GPU cooled before each run. Raw runs

Fig. 4.3eager mode against the defaultchart
Eager mode cost 1.2 to 2.3 percent of the time per token on the L4 Median time per output token against users at the same time on an NVIDIA L4 with Qwen3-8B, three seeds per point, both runs on 2026-10-21. Eager mode is 1.2 to 2.3 percent slower at every concurrency, for example 61.1 against 60.4 ms at one user and 131.4 against 129.2 ms at 64 users. 50 80 110 140 1 2 4 8 16 32 64 users at the same time median ms per token default, -O2 --enforce-eager
On our L4, eager mode was 1.2 to 2.3 percent slower per token at every concurrency. Bands span the lowest and highest of three runs. The two lines sit close because an 8B decode step waits on memory, not on kernel launches.
Users, L4 full-clock sessionMedian TPOT, default / eagerMedian SM clock, default / eager
160.36 / 61.07 ms1,275 / 1,290 MHz
865.75 / 66.98 ms1,485 / 1,515 MHz
32101.79 / 103.11 ms1,275 / 1,313 MHz
64129.15 / 131.42 ms1,005 / 1,020 MHz

The seed ranges did not overlap from 1 to 32 users, so the gap is real, and it is small. On our DGX Spark, eager mode cost 2 to 6 percent of the time per token.

We then ran the compile levels on 2026-10-22, in the throttled session, at 1 and 32 users. The default had three seeds and the other two levels had two. The GPU was throttled for all three: the median clock was 210 MHz at one user and 450 to 548 MHz at 32 users.

Users, L4 throttled sessionMedian TPOT, default / -O0 / -O3
1104.14 / 106.48 / 104.15 ms
32142.67 / 142.04 / 143.85 ms

At one user, -O0 was 2.2 percent slower, and the seed ranges did not overlap. At 32 users, the three levels overlapped. -O3 matched the default, as the code says it should at this version. Because of the low clock, read these as a comparison inside one session, not as speeds you will see.

Decide

Keep the default for production. The graphs and the compile cost about one and a half minutes on our DGX Spark start, and the cache makes later starts faster.

When you test a change and restart often, use -O0. It skips the compile and the graph capture, and it cost us about 2 percent of decode speed. Use --enforce-eager only to debug a kernel, because it also skips the warmup, so the first requests after a start are slow.

vLLM 0.31.0 · db9527a · 2026-10-05 · Edition 2026.10