Speed: tokens per second and first-token time

One request at a time, CuteAFD generates faster: 114-168 tokens/s on the vLLM fork and 120-235 on CuteAFD (K3.25; K4 108-164 and 116-220). A single long prompt gets its first token sooner on CuteAFD (35.1 s and 29.6 s at 128K), a single short one sooner on the vLLM fork (0.25 s and 0.41 s at 1K). With several requests at once the vLLM fork's advantage is time to first token (1K × 8: 1.44 s and 2.76 s); per-stream decode and aggregate throughput there are level or ahead on CuteAFD, except aggregate throughput at 1K × 8. The vLLM fork interleaves chunked prefill with decode, so every request starts early; CuteAFD's prefill is faster per request, but concurrent requests queue for it. On K4 at 16 streams CuteAFD completes 1.37-1.44x the vLLM fork's tokens per second (follow-up K4f, below).

How to read this page

A cell is one prompt length (1K to 128K tokens), one content type (prose, code, reasoning, JSON) and one number of streams (requests in flight at once), measured 3 times; each request generates 1,024 tokens with thinking on, every prompt is unique and every request has its own seed. Decode is the per-stream generation speed, aggregate all generated tokens of a batch per second of wall time, first token the time from sending to the first generated token. With thinking on, the code and JSON cells measure reasoning text about a code or JSON prompt.

K3.25 speed noise: a repeat hours later moved the median by under 2% and single cells by up to 13%; single-cell ratios within ±10% read as level.
K4 speed noise: a ±8% band declared before the run (both engines' drift repeats stayed inside it); single-cell ratios within ±8% read as level.

K3.25 (2026-10-26/27)

Prompt × streamsDecode per stream, tok/s: vLLM forkCuteAFDAggregate, tok/s: vLLM forkCuteAFDFirst token: vLLM forkCuteAFD
1K × 1121-161126-228117-155120-2040.25 s0.41 s
1K × 467-9971-117247-324246-3340.87 s1.22 s
1K × 848-7248-69345-454321-4101.44 s2.76 s
1K × 1626-3929-47378-508397-5162.38 s4.31 s
8K × 1117-168120-23595-12199-1572.11 s1.80 s
8K × 459-7761-98168-207177-2255.48 s5.21 s
8K × 838-5139-54216-250217-2459.48 s9.77 s
8K × 1620-2724-33233-264245-27817.5 s18.9 s
32K × 1114-148121-16958-6665-778.70 s7.26 s
32K × 443-5063-8284-9291-10023.0 s27.1 s
32K × 822-2541-4894-101100-10739.3 s53.4 s
32K × 1612-1323-29100-105107-11272.3 s106.0 s
128K × 1119-150123-16523-2427-2935.1 s29.6 s
128K × 421-2263-90283192.6 s117.0 s

CuteAFD v3.0.1: 1,008 measured requests in 132 batches, 0 errors, 0 replies with </think> in the content; vLLM fork v0.9.2: 1,008 measured requests in 132 batches, 0 errors, 0 replies with </think> in the content. Ranges run over the content types; first token is the median over them. Full grid: t/T-SUMMARY.md.

K3.25: decode speed per stream, CuteAFD ÷ vLLM fork (right is faster on CuteAFD)

What this shows. Per-stream generation speed, CuteAFD ÷ vLLM fork, per prompt length and number of streams; small triangles are content types, the large one their median.

content type, outside the bandcontent type, inside the bandmedian of the content typesvLLM fork (1.0)noise band
1.25x1.5x2x3x4x1x← slowerfaster →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.27x, cells 1.04-1.41x1 stream1K, prose, 1 stream: CuteAFD 125.66 vs vLLM fork 120.69 tok/s per stream = 1.04x1K, code, 1 stream: CuteAFD 196.01 vs vLLM fork 145.24 tok/s per stream = 1.35x1K, reasoning, 1 stream: CuteAFD 228.05 vs vLLM fork 161.21 tok/s per stream = 1.41x1K, JSON, 1 stream: CuteAFD 154.88 vs vLLM fork 130.75 tok/s per stream = 1.18x1.27x (1.04-1.41x)4 streams: median over 4 content cells 1.05x, cells 1.03-1.18x4 streams1K, prose, 4 streams: CuteAFD 71.22 vs vLLM fork 67.09 tok/s per stream = 1.06x1K, code, 4 streams: CuteAFD 91.95 vs vLLM fork 88.92 tok/s per stream = 1.03x1K, reasoning, 4 streams: CuteAFD 116.99 vs vLLM fork 99.42 tok/s per stream = 1.18x1K, JSON, 4 streams: CuteAFD 84.76 vs vLLM fork 82.25 tok/s per stream = 1.03x1.05x (1.03-1.18x)8 streams: median over 4 content cells 0.98x, cells 0.94-0.99x8 streams1K, prose, 8 streams: CuteAFD 48.01 vs vLLM fork 48.26 tok/s per stream = 0.99x1K, code, 8 streams: CuteAFD 58.40 vs vLLM fork 61.97 tok/s per stream = 0.94x1K, reasoning, 8 streams: CuteAFD 69.32 vs vLLM fork 71.84 tok/s per stream = 0.96x1K, JSON, 8 streams: CuteAFD 56.47 vs vLLM fork 57.07 tok/s per stream = 0.99x0.98x (0.94-0.99x)16 streams: median over 4 content cells 1.14x, cells 1.08-1.21x16 streams1K, prose, 16 streams: CuteAFD 29.21 vs vLLM fork 26.38 tok/s per stream = 1.11x1K, code, 16 streams: CuteAFD 39.10 vs vLLM fork 33.56 tok/s per stream = 1.16x1K, reasoning, 16 streams: CuteAFD 46.55 vs vLLM fork 38.54 tok/s per stream = 1.21x1K, JSON, 16 streams: CuteAFD 34.99 vs vLLM fork 32.46 tok/s per stream = 1.08x1.14x (1.08-1.21x)1 stream: median over 4 content cells 1.14x, cells 1.02-1.39x1 stream8K, prose, 1 stream: CuteAFD 119.76 vs vLLM fork 117.36 tok/s per stream = 1.02x8K, code, 1 stream: CuteAFD 174.59 vs vLLM fork 151.06 tok/s per stream = 1.16x8K, reasoning, 1 stream: CuteAFD 234.71 vs vLLM fork 168.36 tok/s per stream = 1.39x8K, JSON, 1 stream: CuteAFD 146.12 vs vLLM fork 130.12 tok/s per stream = 1.12x1.14x (1.02-1.39x)4 streams: median over 4 content cells 1.07x, cells 1.04-1.27x4 streams8K, prose, 4 streams: CuteAFD 61.42 vs vLLM fork 59.29 tok/s per stream = 1.04x8K, code, 4 streams: CuteAFD 78.09 vs vLLM fork 73.30 tok/s per stream = 1.07x8K, reasoning, 4 streams: CuteAFD 98.13 vs vLLM fork 77.42 tok/s per stream = 1.27x8K, JSON, 4 streams: CuteAFD 74.08 vs vLLM fork 68.58 tok/s per stream = 1.08x1.07x (1.04-1.27x)8 streams: median over 4 content cells 1.04x, cells 1.02-1.10x8 streams8K, prose, 8 streams: CuteAFD 39.33 vs vLLM fork 38.50 tok/s per stream = 1.02x8K, code, 8 streams: CuteAFD 49.19 vs vLLM fork 44.53 tok/s per stream = 1.10x8K, reasoning, 8 streams: CuteAFD 53.76 vs vLLM fork 50.90 tok/s per stream = 1.06x8K, JSON, 8 streams: CuteAFD 44.75 vs vLLM fork 43.29 tok/s per stream = 1.03x1.04x (1.02-1.10x)16 streams: median over 4 content cells 1.18x, cells 1.10-1.23x16 streams8K, prose, 16 streams: CuteAFD 24.13 vs vLLM fork 20.47 tok/s per stream = 1.18x8K, code, 16 streams: CuteAFD 28.36 vs vLLM fork 23.86 tok/s per stream = 1.19x8K, reasoning, 16 streams: CuteAFD 32.98 vs vLLM fork 26.83 tok/s per stream = 1.23x8K, JSON, 16 streams: CuteAFD 25.68 vs vLLM fork 23.36 tok/s per stream = 1.10x1.18x (1.10-1.23x)1 stream: median over 2 content cells 1.10x, cells 1.06-1.14x1 stream32K, prose, 1 stream: CuteAFD 121.41 vs vLLM fork 114.43 tok/s per stream = 1.06x32K, code, 1 stream: CuteAFD 169.28 vs vLLM fork 148.01 tok/s per stream = 1.14x1.10x (1.06-1.14x)4 streams: median over 2 content cells 1.55x, cells 1.47-1.63x4 streams32K, prose, 4 streams: CuteAFD 62.99 vs vLLM fork 42.78 tok/s per stream = 1.47x32K, code, 4 streams: CuteAFD 81.64 vs vLLM fork 50.18 tok/s per stream = 1.63x1.55x (1.47-1.63x)8 streams: median over 2 content cells 1.86x, cells 1.84-1.88x8 streams32K, prose, 8 streams: CuteAFD 41.30 vs vLLM fork 22.39 tok/s per stream = 1.84x32K, code, 8 streams: CuteAFD 47.86 vs vLLM fork 25.49 tok/s per stream = 1.88x1.86x (1.84-1.88x)16 streams: median over 2 content cells 2.10x, cells 1.96-2.24x16 streams32K, prose, 16 streams: CuteAFD 23.08 vs vLLM fork 11.80 tok/s per stream = 1.96x32K, code, 16 streams: CuteAFD 29.16 vs vLLM fork 13.02 tok/s per stream = 2.24x2.10x (1.96-2.24x)1 stream: median over 2 content cells 1.06x, cells 1.03-1.10x1 stream128K, prose, 1 stream: CuteAFD 122.85 vs vLLM fork 119.46 tok/s per stream = 1.03x128K, code, 1 stream: CuteAFD 165.33 vs vLLM fork 150.22 tok/s per stream = 1.10x1.06x (1.03-1.10x)4 streams: median over 2 content cells 3.48x, cells 2.94-4.03x4 streams128K, prose, 4 streams: CuteAFD 62.69 vs vLLM fork 21.34 tok/s per stream = 2.94x128K, code, 4 streams: CuteAFD 89.60 vs vLLM fork 22.24 tok/s per stream = 4.03x3.48x (2.94-4.03x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, tok/s per streamCuteAFD, tok/s per streamCuteAFD ÷ vLLM forkReading
1Kprose1120.69125.661.04xlevel
1Kcode1145.24196.011.35xoutside the band
1Kreasoning1161.21228.051.41xoutside the band
1KJSON1130.75154.881.18xoutside the band
1Kprose467.0971.221.06xlevel
1Kcode488.9291.951.03xlevel
1Kreasoning499.42116.991.18xoutside the band
1KJSON482.2584.761.03xlevel
1Kprose848.2648.010.99xlevel
1Kcode861.9758.400.94xlevel
1Kreasoning871.8469.320.96xlevel
1KJSON857.0756.470.99xlevel
1Kprose1626.3829.211.11xoutside the band
1Kcode1633.5639.101.16xoutside the band
1Kreasoning1638.5446.551.21xoutside the band
1KJSON1632.4634.991.08xlevel
8Kprose1117.36119.761.02xlevel
8Kcode1151.06174.591.16xoutside the band
8Kreasoning1168.36234.711.39xoutside the band
8KJSON1130.12146.121.12xoutside the band
8Kprose459.2961.421.04xlevel
8Kcode473.3078.091.07xlevel
8Kreasoning477.4298.131.27xoutside the band
8KJSON468.5874.081.08xlevel
8Kprose838.5039.331.02xlevel
8Kcode844.5349.191.10xoutside the band
8Kreasoning850.9053.761.06xlevel
8KJSON843.2944.751.03xlevel
8Kprose1620.4724.131.18xoutside the band
8Kcode1623.8628.361.19xoutside the band
8Kreasoning1626.8332.981.23xoutside the band
8KJSON1623.3625.681.10xlevel
32Kprose1114.43121.411.06xlevel
32Kcode1148.01169.281.14xoutside the band
32Kprose442.7862.991.47xoutside the band
32Kcode450.1881.641.63xoutside the band
32Kprose822.3941.301.84xoutside the band
32Kcode825.4947.861.88xoutside the band
32Kprose1611.8023.081.96xoutside the band
32Kcode1613.0229.162.24xoutside the band
128Kprose1119.46122.851.03xlevel
128Kcode1150.22165.331.10xoutside the band
128Kprose421.3462.692.94xoutside the band
128Kcode422.2489.604.03xoutside the band
K3.25: time to first token, CuteAFD ÷ vLLM fork (left is sooner on CuteAFD)

What this shows. Time from sending a request to its first token, CuteAFD ÷ vLLM fork; small triangles are content types.

content typemedian of the content typesvLLM fork (1.0)noise band, for scale
0.8x0.9x1.1x1.25x1.5x2x1x← soonerlater →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.62x, cells 1.57-1.65x1 stream1K, prose, 1 stream: CuteAFD 0.41 vs vLLM fork 0.25 s = 1.65x1K, code, 1 stream: CuteAFD 0.41 vs vLLM fork 0.25 s = 1.63x1K, reasoning, 1 stream: CuteAFD 0.41 vs vLLM fork 0.26 s = 1.57x1K, JSON, 1 stream: CuteAFD 0.40 vs vLLM fork 0.25 s = 1.61x1.62x (1.57-1.65x)4 streams: median over 4 content cells 1.40x, cells 1.40-1.41x4 streams1K, prose, 4 streams: CuteAFD 1.22 vs vLLM fork 0.87 s = 1.40x1K, code, 4 streams: CuteAFD 1.22 vs vLLM fork 0.87 s = 1.41x1K, reasoning, 4 streams: CuteAFD 1.22 vs vLLM fork 0.87 s = 1.40x1K, JSON, 4 streams: CuteAFD 1.21 vs vLLM fork 0.86 s = 1.40x1.40x (1.40-1.41x)8 streams: median over 4 content cells 1.91x, cells 1.90-1.93x8 streams1K, prose, 8 streams: CuteAFD 2.76 vs vLLM fork 1.45 s = 1.91x1K, code, 8 streams: CuteAFD 2.77 vs vLLM fork 1.43 s = 1.93x1K, reasoning, 8 streams: CuteAFD 2.75 vs vLLM fork 1.45 s = 1.90x1K, JSON, 8 streams: CuteAFD 2.74 vs vLLM fork 1.44 s = 1.91x1.91x (1.90-1.93x)16 streams: median over 4 content cells 1.80x, cells 1.79-1.83x16 streams1K, prose, 16 streams: CuteAFD 4.32 vs vLLM fork 2.39 s = 1.80x1K, code, 16 streams: CuteAFD 4.34 vs vLLM fork 2.37 s = 1.83x1K, reasoning, 16 streams: CuteAFD 4.30 vs vLLM fork 2.39 s = 1.80x1K, JSON, 16 streams: CuteAFD 4.25 vs vLLM fork 2.37 s = 1.79x1.80x (1.79-1.83x)1 stream: median over 4 content cells 0.86x, cells 0.85-0.86x1 stream8K, prose, 1 stream: CuteAFD 1.80 vs vLLM fork 2.11 s = 0.86x8K, code, 1 stream: CuteAFD 1.80 vs vLLM fork 2.10 s = 0.86x8K, reasoning, 1 stream: CuteAFD 1.81 vs vLLM fork 2.11 s = 0.86x8K, JSON, 1 stream: CuteAFD 1.80 vs vLLM fork 2.11 s = 0.85x0.86x (0.85-0.86x)4 streams: median over 4 content cells 0.95x, cells 0.95-0.96x4 streams8K, prose, 4 streams: CuteAFD 5.21 vs vLLM fork 5.49 s = 0.95x8K, code, 4 streams: CuteAFD 5.21 vs vLLM fork 5.46 s = 0.96x8K, reasoning, 4 streams: CuteAFD 5.24 vs vLLM fork 5.50 s = 0.95x8K, JSON, 4 streams: CuteAFD 5.21 vs vLLM fork 5.47 s = 0.95x0.95x (0.95-0.96x)8 streams: median over 4 content cells 1.03x, cells 1.03-1.03x8 streams8K, prose, 8 streams: CuteAFD 9.77 vs vLLM fork 9.50 s = 1.03x8K, code, 8 streams: CuteAFD 9.78 vs vLLM fork 9.45 s = 1.03x8K, reasoning, 8 streams: CuteAFD 9.81 vs vLLM fork 9.50 s = 1.03x8K, JSON, 8 streams: CuteAFD 9.76 vs vLLM fork 9.47 s = 1.03x1.03x (1.03-1.03x)16 streams: median over 4 content cells 1.08x, cells 1.08-1.08x16 streams8K, prose, 16 streams: CuteAFD 18.85 vs vLLM fork 17.52 s = 1.08x8K, code, 16 streams: CuteAFD 18.86 vs vLLM fork 17.43 s = 1.08x8K, reasoning, 16 streams: CuteAFD 18.93 vs vLLM fork 17.51 s = 1.08x8K, JSON, 16 streams: CuteAFD 18.89 vs vLLM fork 17.47 s = 1.08x1.08x (1.08-1.08x)1 stream: median over 2 content cells 0.83x, cells 0.83-0.84x1 stream32K, prose, 1 stream: CuteAFD 7.26 vs vLLM fork 8.71 s = 0.83x32K, code, 1 stream: CuteAFD 7.27 vs vLLM fork 8.70 s = 0.84x0.83x (0.83-0.84x)4 streams: median over 2 content cells 1.18x, cells 1.18-1.18x4 streams32K, prose, 4 streams: CuteAFD 27.09 vs vLLM fork 23.05 s = 1.18x32K, code, 4 streams: CuteAFD 27.07 vs vLLM fork 22.98 s = 1.18x1.18x (1.18-1.18x)8 streams: median over 2 content cells 1.36x, cells 1.36-1.36x8 streams32K, prose, 8 streams: CuteAFD 53.40 vs vLLM fork 39.31 s = 1.36x32K, code, 8 streams: CuteAFD 53.34 vs vLLM fork 39.21 s = 1.36x1.36x (1.36-1.36x)16 streams: median over 2 content cells 1.47x, cells 1.46-1.47x16 streams32K, prose, 16 streams: CuteAFD 106.03 vs vLLM fork 72.39 s = 1.46x32K, code, 16 streams: CuteAFD 105.94 vs vLLM fork 72.19 s = 1.47x1.47x (1.46-1.47x)1 stream: median over 2 content cells 0.84x, cells 0.84-0.84x1 stream128K, prose, 1 stream: CuteAFD 29.58 vs vLLM fork 35.08 s = 0.84x128K, code, 1 stream: CuteAFD 29.57 vs vLLM fork 35.02 s = 0.84x0.84x (0.84-0.84x)4 streams: median over 2 content cells 1.26x, cells 1.25-1.28x4 streams128K, prose, 4 streams: CuteAFD 116.03 vs vLLM fork 92.64 s = 1.25x128K, code, 4 streams: CuteAFD 117.96 vs vLLM fork 92.47 s = 1.28x1.26x (1.25-1.28x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, sCuteAFD, sCuteAFD ÷ vLLM forkReading
1Kprose10.250.411.65xfor scale only
1Kcode10.250.411.63xfor scale only
1Kreasoning10.260.411.57xfor scale only
1KJSON10.250.401.61xfor scale only
1Kprose40.871.221.40xfor scale only
1Kcode40.871.221.41xfor scale only
1Kreasoning40.871.221.40xfor scale only
1KJSON40.861.211.40xfor scale only
1Kprose81.452.761.91xfor scale only
1Kcode81.432.771.93xfor scale only
1Kreasoning81.452.751.90xfor scale only
1KJSON81.442.741.91xfor scale only
1Kprose162.394.321.80xfor scale only
1Kcode162.374.341.83xfor scale only
1Kreasoning162.394.301.80xfor scale only
1KJSON162.374.251.79xfor scale only
8Kprose12.111.800.86xfor scale only
8Kcode12.101.800.86xfor scale only
8Kreasoning12.111.810.86xfor scale only
8KJSON12.111.800.85xfor scale only
8Kprose45.495.210.95xfor scale only
8Kcode45.465.210.96xfor scale only
8Kreasoning45.505.240.95xfor scale only
8KJSON45.475.210.95xfor scale only
8Kprose89.509.771.03xfor scale only
8Kcode89.459.781.03xfor scale only
8Kreasoning89.509.811.03xfor scale only
8KJSON89.479.761.03xfor scale only
8Kprose1617.5218.851.08xfor scale only
8Kcode1617.4318.861.08xfor scale only
8Kreasoning1617.5118.931.08xfor scale only
8KJSON1617.4718.891.08xfor scale only
32Kprose18.717.260.83xfor scale only
32Kcode18.707.270.84xfor scale only
32Kprose423.0527.091.18xfor scale only
32Kcode422.9827.071.18xfor scale only
32Kprose839.3153.401.36xfor scale only
32Kcode839.2153.341.36xfor scale only
32Kprose1672.39106.031.46xfor scale only
32Kcode1672.19105.941.47xfor scale only
128Kprose135.0829.580.84xfor scale only
128Kcode135.0229.570.84xfor scale only
128Kprose492.64116.031.25xfor scale only
128Kcode492.47117.961.28xfor scale only
K3.25: aggregate throughput, CuteAFD ÷ vLLM fork (right is more tokens per second on CuteAFD)

What this shows. All generated tokens of a batch per second of wall time, CuteAFD ÷ vLLM fork; small triangles are content types.

content type, outside the bandcontent type, inside the bandmedian of the content typesvLLM fork (1.0)noise band
0.9x1.1x1.25x1x← fewer tokens/smore tokens/s →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.22x, cells 1.02-1.32x1 stream1K, prose, 1 stream: CuteAFD 119.82 vs vLLM fork 117.40 tok/s = 1.02x1K, code, 1 stream: CuteAFD 181.86 vs vLLM fork 140.36 tok/s = 1.30x1K, reasoning, 1 stream: CuteAFD 204.39 vs vLLM fork 155.29 tok/s = 1.32x1K, JSON, 1 stream: CuteAFD 146.08 vs vLLM fork 126.91 tok/s = 1.15x1.22x (1.02-1.32x)4 streams: median over 4 content cells 1.00x, cells 0.96-1.05x4 streams1K, prose, 4 streams: CuteAFD 246.10 vs vLLM fork 247.24 tok/s = 1.00x1K, code, 4 streams: CuteAFD 309.91 vs vLLM fork 324.34 tok/s = 0.96x1K, reasoning, 4 streams: CuteAFD 334.07 vs vLLM fork 317.49 tok/s = 1.05x1K, JSON, 4 streams: CuteAFD 296.62 vs vLLM fork 294.75 tok/s = 1.01x1.00x (0.96-1.05x)8 streams: median over 4 content cells 0.91x, cells 0.87-0.93x8 streams1K, prose, 8 streams: CuteAFD 321.45 vs vLLM fork 344.89 tok/s = 0.93x1K, code, 8 streams: CuteAFD 381.11 vs vLLM fork 439.53 tok/s = 0.87x1K, reasoning, 8 streams: CuteAFD 409.96 vs vLLM fork 454.10 tok/s = 0.90x1K, JSON, 8 streams: CuteAFD 379.59 vs vLLM fork 416.01 tok/s = 0.91x0.91x (0.87-0.93x)16 streams: median over 4 content cells 1.02x, cells 0.98-1.05x16 streams1K, prose, 16 streams: CuteAFD 397.02 vs vLLM fork 377.91 tok/s = 1.05x1K, code, 16 streams: CuteAFD 483.61 vs vLLM fork 476.84 tok/s = 1.01x1K, reasoning, 16 streams: CuteAFD 516.24 vs vLLM fork 508.08 tok/s = 1.02x1K, JSON, 16 streams: CuteAFD 462.06 vs vLLM fork 473.13 tok/s = 0.98x1.02x (0.98-1.05x)1 stream: median over 4 content cells 1.15x, cells 1.05-1.30x1 stream8K, prose, 1 stream: CuteAFD 98.96 vs vLLM fork 94.57 tok/s = 1.05x8K, code, 1 stream: CuteAFD 133.46 vs vLLM fork 115.36 tok/s = 1.16x8K, reasoning, 1 stream: CuteAFD 157.05 vs vLLM fork 121.16 tok/s = 1.30x8K, JSON, 1 stream: CuteAFD 116.33 vs vLLM fork 102.57 tok/s = 1.13x1.15x (1.05-1.30x)4 streams: median over 4 content cells 1.04x, cells 0.99-1.11x4 streams8K, prose, 4 streams: CuteAFD 177.21 vs vLLM fork 168.27 tok/s = 1.05x8K, code, 4 streams: CuteAFD 205.51 vs vLLM fork 207.36 tok/s = 0.99x8K, reasoning, 4 streams: CuteAFD 225.06 vs vLLM fork 202.60 tok/s = 1.11x8K, JSON, 4 streams: CuteAFD 199.98 vs vLLM fork 194.24 tok/s = 1.03x1.04x (0.99-1.11x)8 streams: median over 4 content cells 0.99x, cells 0.96-1.00x8 streams8K, prose, 8 streams: CuteAFD 216.66 vs vLLM fork 215.63 tok/s = 1.00x8K, code, 8 streams: CuteAFD 244.66 vs vLLM fork 247.97 tok/s = 0.99x8K, reasoning, 8 streams: CuteAFD 239.74 vs vLLM fork 249.98 tok/s = 0.96x8K, JSON, 8 streams: CuteAFD 239.35 vs vLLM fork 242.22 tok/s = 0.99x0.99x (0.96-1.00x)16 streams: median over 4 content cells 1.05x, cells 1.04-1.09x16 streams8K, prose, 16 streams: CuteAFD 244.94 vs vLLM fork 233.13 tok/s = 1.05x8K, code, 16 streams: CuteAFD 277.99 vs vLLM fork 263.72 tok/s = 1.05x8K, reasoning, 16 streams: CuteAFD 277.71 vs vLLM fork 255.54 tok/s = 1.09x8K, JSON, 16 streams: CuteAFD 271.14 vs vLLM fork 260.03 tok/s = 1.04x1.05x (1.04-1.09x)1 stream: median over 2 content cells 1.15x, cells 1.13-1.17x1 stream32K, prose, 1 stream: CuteAFD 65.21 vs vLLM fork 57.83 tok/s = 1.13x32K, code, 1 stream: CuteAFD 76.94 vs vLLM fork 65.53 tok/s = 1.17x1.15x (1.13-1.17x)4 streams: median over 2 content cells 1.08x, cells 1.08-1.08x4 streams32K, prose, 4 streams: CuteAFD 91.10 vs vLLM fork 84.17 tok/s = 1.08x32K, code, 4 streams: CuteAFD 99.51 vs vLLM fork 92.28 tok/s = 1.08x1.08x (1.08-1.08x)8 streams: median over 2 content cells 1.06x, cells 1.06-1.06x8 streams32K, prose, 8 streams: CuteAFD 99.67 vs vLLM fork 94.35 tok/s = 1.06x32K, code, 8 streams: CuteAFD 106.65 vs vLLM fork 100.50 tok/s = 1.06x1.06x (1.06-1.06x)16 streams: median over 2 content cells 1.07x, cells 1.07-1.07x16 streams32K, prose, 16 streams: CuteAFD 106.62 vs vLLM fork 99.56 tok/s = 1.07x32K, code, 16 streams: CuteAFD 112.06 vs vLLM fork 105.05 tok/s = 1.07x1.07x (1.07-1.07x)1 stream: median over 2 content cells 1.16x, cells 1.15-1.17x1 stream128K, prose, 1 stream: CuteAFD 27.01 vs vLLM fork 23.47 tok/s = 1.15x128K, code, 1 stream: CuteAFD 28.65 vs vLLM fork 24.48 tok/s = 1.17x1.16x (1.15-1.17x)4 streams: median over 2 content cells 1.11x, cells 1.11-1.11x4 streams128K, prose, 4 streams: CuteAFD 30.60 vs vLLM fork 27.52 tok/s = 1.11x128K, code, 4 streams: CuteAFD 31.35 vs vLLM fork 28.23 tok/s = 1.11x1.11x (1.11-1.11x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, tok/sCuteAFD, tok/sCuteAFD ÷ vLLM forkReading
1Kprose1117.40119.821.02xlevel
1Kcode1140.36181.861.30xoutside the band
1Kreasoning1155.29204.391.32xoutside the band
1KJSON1126.91146.081.15xoutside the band
1Kprose4247.24246.101.00xlevel
1Kcode4324.34309.910.96xlevel
1Kreasoning4317.49334.071.05xlevel
1KJSON4294.75296.621.01xlevel
1Kprose8344.89321.450.93xlevel
1Kcode8439.53381.110.87xoutside the band
1Kreasoning8454.10409.960.90xlevel
1KJSON8416.01379.590.91xlevel
1Kprose16377.91397.021.05xlevel
1Kcode16476.84483.611.01xlevel
1Kreasoning16508.08516.241.02xlevel
1KJSON16473.13462.060.98xlevel
8Kprose194.5798.961.05xlevel
8Kcode1115.36133.461.16xoutside the band
8Kreasoning1121.16157.051.30xoutside the band
8KJSON1102.57116.331.13xoutside the band
8Kprose4168.27177.211.05xlevel
8Kcode4207.36205.510.99xlevel
8Kreasoning4202.60225.061.11xoutside the band
8KJSON4194.24199.981.03xlevel
8Kprose8215.63216.661.00xlevel
8Kcode8247.97244.660.99xlevel
8Kreasoning8249.98239.740.96xlevel
8KJSON8242.22239.350.99xlevel
8Kprose16233.13244.941.05xlevel
8Kcode16263.72277.991.05xlevel
8Kreasoning16255.54277.711.09xlevel
8KJSON16260.03271.141.04xlevel
32Kprose157.8365.211.13xoutside the band
32Kcode165.5376.941.17xoutside the band
32Kprose484.1791.101.08xlevel
32Kcode492.2899.511.08xlevel
32Kprose894.3599.671.06xlevel
32Kcode8100.50106.651.06xlevel
32Kprose1699.56106.621.07xlevel
32Kcode16105.05112.061.07xlevel
128Kprose123.4727.011.15xoutside the band
128Kcode124.4828.651.17xoutside the band
128Kprose427.5230.601.11xoutside the band
128Kcode428.2331.351.11xoutside the band

K4 (2026-10-27)

The K4 grid is smaller: 1 and 4 streams at 1K-32K and 1 stream at 128K, set once for every arm of its frozen protocol. Readings per cell use the declared band.

Prompt × streamsDecode per stream, tok/s: vLLM forkCuteAFDAggregate, tok/s: vLLM forkCuteAFDFirst token: vLLM forkCuteAFD
1K × 1113-164127-219110-157121-2000.27 s0.42 s
1K × 460-9371-114222-290237-3230.87 s1.26 s
8K × 1111-160116-22090-12099-1532.20 s1.84 s
8K × 455-7263-83154-184176-2175.72 s5.30 s
32K × 1108-142121-17056-6365-769.05 s7.38 s
32K × 441-4763-7579-8689-9724.0 s27.6 s
128K × 1113-145120-17223-2427-2836.4 s30.1 s

vLLM: 264 measured requests, 0 errors; CuteAFD: 264 measured requests, 0 errors. Prompt-token counts identical on every cell except the 128K code cell (12 CuteAFD requests longer: those prompts hold literal <think> text, which vLLM parses as a special token).

K4: decode speed per stream, CuteAFD ÷ vLLM fork (right is faster on CuteAFD)

What this shows. Per-stream generation speed, CuteAFD ÷ vLLM fork, per prompt length and number of streams; small triangles are content types, the large one their median.

content type, outside the bandcontent type, inside the bandmedian of the content typesvLLM fork (1.0)noise band
0.9x1.1x1.25x1.5x1x← slowerfaster →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.16x, cells 1.12-1.34x1 stream1K, prose, 1 stream: CuteAFD 126.59 vs vLLM fork 113.18 tok/s per stream = 1.12x (faster)1K, code, 1 stream: CuteAFD 174.77 vs vLLM fork 145.69 tok/s per stream = 1.20x (faster)1K, reasoning, 1 stream: CuteAFD 219.33 vs vLLM fork 164.10 tok/s per stream = 1.34x (faster)1K, JSON, 1 stream: CuteAFD 145.26 vs vLLM fork 129.95 tok/s per stream = 1.12x (faster)1.16x (1.12-1.34x)4 streams: median over 4 content cells 1.17x, cells 1.15-1.23x4 streams1K, prose, 4 streams: CuteAFD 70.60 vs vLLM fork 59.51 tok/s per stream = 1.19x (faster)1K, code, 4 streams: CuteAFD 89.93 vs vLLM fork 78.40 tok/s per stream = 1.15x (faster)1K, reasoning, 4 streams: CuteAFD 113.68 vs vLLM fork 92.69 tok/s per stream = 1.23x (faster)1K, JSON, 4 streams: CuteAFD 83.93 vs vLLM fork 72.58 tok/s per stream = 1.16x (faster)1.17x (1.15-1.23x)1 stream: median over 4 content cells 1.20x, cells 1.05-1.38x1 stream8K, prose, 1 stream: CuteAFD 115.93 vs vLLM fork 110.52 tok/s per stream = 1.05x (level)8K, code, 1 stream: CuteAFD 178.78 vs vLLM fork 146.66 tok/s per stream = 1.22x (faster)8K, reasoning, 1 stream: CuteAFD 220.40 vs vLLM fork 159.60 tok/s per stream = 1.38x (faster)8K, JSON, 1 stream: CuteAFD 153.01 vs vLLM fork 130.12 tok/s per stream = 1.18x (faster)1.20x (1.05-1.38x)4 streams: median over 4 content cells 1.14x, cells 1.11-1.15x4 streams8K, prose, 4 streams: CuteAFD 62.67 vs vLLM fork 54.70 tok/s per stream = 1.15x (faster)8K, code, 4 streams: CuteAFD 75.57 vs vLLM fork 68.39 tok/s per stream = 1.11x (faster)8K, reasoning, 4 streams: CuteAFD 83.05 vs vLLM fork 72.11 tok/s per stream = 1.15x (faster)8K, JSON, 4 streams: CuteAFD 68.98 vs vLLM fork 60.71 tok/s per stream = 1.14x (faster)1.14x (1.11-1.15x)1 stream: median over 2 content cells 1.16x, cells 1.12-1.19x1 stream32K, prose, 1 stream: CuteAFD 121.43 vs vLLM fork 108.47 tok/s per stream = 1.12x (faster)32K, code, 1 stream: CuteAFD 169.68 vs vLLM fork 142.37 tok/s per stream = 1.19x (faster)1.16x (1.12-1.19x)4 streams: median over 2 content cells 1.56x, cells 1.54-1.59x4 streams32K, prose, 4 streams: CuteAFD 63.07 vs vLLM fork 41.04 tok/s per stream = 1.54x (faster)32K, code, 4 streams: CuteAFD 75.02 vs vLLM fork 47.30 tok/s per stream = 1.59x (faster)1.56x (1.54-1.59x)1 stream: median over 2 content cells 1.12x, cells 1.06-1.19x1 stream128K, prose, 1 stream: CuteAFD 119.92 vs vLLM fork 113.23 tok/s per stream = 1.06x (level)128K, code, 1 stream: CuteAFD 171.84 vs vLLM fork 144.63 tok/s per stream = 1.19x (faster)1.12x (1.06-1.19x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, tok/s per streamCuteAFD, tok/s per streamCuteAFD ÷ vLLM forkReading
1Kprose1113.18126.591.12xfaster
1Kcode1145.69174.771.20xfaster
1Kreasoning1164.10219.331.34xfaster
1KJSON1129.95145.261.12xfaster
1Kprose459.5170.601.19xfaster
1Kcode478.4089.931.15xfaster
1Kreasoning492.69113.681.23xfaster
1KJSON472.5883.931.16xfaster
8Kprose1110.52115.931.05xlevel
8Kcode1146.66178.781.22xfaster
8Kreasoning1159.60220.401.38xfaster
8KJSON1130.12153.011.18xfaster
8Kprose454.7062.671.15xfaster
8Kcode468.3975.571.11xfaster
8Kreasoning472.1183.051.15xfaster
8KJSON460.7168.981.14xfaster
32Kprose1108.47121.431.12xfaster
32Kcode1142.37169.681.19xfaster
32Kprose441.0463.071.54xfaster
32Kcode447.3075.021.59xfaster
128Kprose1113.23119.921.06xlevel
128Kcode1144.63171.841.19xfaster
K4: time to first token, CuteAFD ÷ vLLM fork (left is sooner on CuteAFD)

What this shows. Time from sending a request to its first token, CuteAFD ÷ vLLM fork; small triangles are content types.

content typemedian of the content typesvLLM fork (1.0)noise band, for scale
0.8x0.9x1.1x1.25x1.5x1x← soonerlater →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.56x, cells 1.55-1.60x1 stream1K, prose, 1 stream: CuteAFD 0.42 vs vLLM fork 0.26 s = 1.60x1K, code, 1 stream: CuteAFD 0.42 vs vLLM fork 0.27 s = 1.57x1K, reasoning, 1 stream: CuteAFD 0.42 vs vLLM fork 0.27 s = 1.55x1K, JSON, 1 stream: CuteAFD 0.42 vs vLLM fork 0.27 s = 1.55x1.56x (1.55-1.60x)4 streams: median over 4 content cells 1.44x, cells 1.25-1.52x4 streams1K, prose, 4 streams: CuteAFD 1.26 vs vLLM fork 0.83 s = 1.51x1K, code, 4 streams: CuteAFD 1.26 vs vLLM fork 0.83 s = 1.52x1K, reasoning, 4 streams: CuteAFD 1.26 vs vLLM fork 1.01 s = 1.25x1K, JSON, 4 streams: CuteAFD 1.25 vs vLLM fork 0.90 s = 1.38x1.44x (1.25-1.52x)1 stream: median over 4 content cells 0.83x, cells 0.83-0.84x1 stream8K, prose, 1 stream: CuteAFD 1.84 vs vLLM fork 2.20 s = 0.84x8K, code, 1 stream: CuteAFD 1.83 vs vLLM fork 2.20 s = 0.83x8K, reasoning, 1 stream: CuteAFD 1.84 vs vLLM fork 2.20 s = 0.83x8K, JSON, 1 stream: CuteAFD 1.83 vs vLLM fork 2.20 s = 0.83x0.83x (0.83-0.84x)4 streams: median over 4 content cells 0.93x, cells 0.92-0.93x4 streams8K, prose, 4 streams: CuteAFD 5.30 vs vLLM fork 5.73 s = 0.92x8K, code, 4 streams: CuteAFD 5.30 vs vLLM fork 5.71 s = 0.93x8K, reasoning, 4 streams: CuteAFD 5.32 vs vLLM fork 5.73 s = 0.93x8K, JSON, 4 streams: CuteAFD 5.30 vs vLLM fork 5.72 s = 0.93x0.93x (0.92-0.93x)1 stream: median over 2 content cells 0.82x, cells 0.81-0.82x1 stream32K, prose, 1 stream: CuteAFD 7.38 vs vLLM fork 9.04 s = 0.82x32K, code, 1 stream: CuteAFD 7.37 vs vLLM fork 9.05 s = 0.81x0.82x (0.81-0.82x)4 streams: median over 2 content cells 1.15x, cells 1.15-1.15x4 streams32K, prose, 4 streams: CuteAFD 27.57 vs vLLM fork 24.05 s = 1.15x32K, code, 4 streams: CuteAFD 27.55 vs vLLM fork 24.00 s = 1.15x1.15x (1.15-1.15x)1 stream: median over 2 content cells 0.83x, cells 0.83-0.83x1 stream128K, prose, 1 stream: CuteAFD 30.09 vs vLLM fork 36.42 s = 0.83x128K, code, 1 stream: CuteAFD 30.08 vs vLLM fork 36.30 s = 0.83x0.83x (0.83-0.83x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, sCuteAFD, sCuteAFD ÷ vLLM forkReading
1Kprose10.260.421.60xfor scale only
1Kcode10.270.421.57xfor scale only
1Kreasoning10.270.421.55xfor scale only
1KJSON10.270.421.55xfor scale only
1Kprose40.831.261.51xfor scale only
1Kcode40.831.261.52xfor scale only
1Kreasoning41.011.261.25xfor scale only
1KJSON40.901.251.38xfor scale only
8Kprose12.201.840.84xfor scale only
8Kcode12.201.830.83xfor scale only
8Kreasoning12.201.840.83xfor scale only
8KJSON12.201.830.83xfor scale only
8Kprose45.735.300.92xfor scale only
8Kcode45.715.300.93xfor scale only
8Kreasoning45.735.320.93xfor scale only
8KJSON45.725.300.93xfor scale only
32Kprose19.047.380.82xfor scale only
32Kcode19.057.370.81xfor scale only
32Kprose424.0527.571.15xfor scale only
32Kcode424.0027.551.15xfor scale only
128Kprose136.4230.090.83xfor scale only
128Kcode136.3030.080.83xfor scale only
K4: aggregate throughput, CuteAFD ÷ vLLM fork (right is more tokens per second on CuteAFD)

What this shows. All generated tokens of a batch per second of wall time, CuteAFD ÷ vLLM fork; small triangles are content types.

content type, outside the bandcontent type, inside the bandmedian of the content typesvLLM fork (1.0)noise band
1.1x1.25x1x← fewer tokens/smore tokens/s →vLLM fork1K prompt8K prompt32K prompt128K prompt1 stream: median over 4 content cells 1.12x, cells 1.10-1.27x1 stream1K, prose, 1 stream: CuteAFD 121.23 vs vLLM fork 110.03 tok/s = 1.10x (faster)1K, code, 1 stream: CuteAFD 162.21 vs vLLM fork 141.75 tok/s = 1.14x (faster)1K, reasoning, 1 stream: CuteAFD 199.71 vs vLLM fork 157.15 tok/s = 1.27x (faster)1K, JSON, 1 stream: CuteAFD 138.36 vs vLLM fork 125.67 tok/s = 1.10x (faster)1.12x (1.10-1.27x)4 streams: median over 4 content cells 1.07x, cells 1.06-1.12x4 streams1K, prose, 4 streams: CuteAFD 237.47 vs vLLM fork 222.21 tok/s = 1.07x (level)1K, code, 4 streams: CuteAFD 297.32 vs vLLM fork 280.17 tok/s = 1.06x (level)1K, reasoning, 4 streams: CuteAFD 323.21 vs vLLM fork 289.58 tok/s = 1.12x (faster)1K, JSON, 4 streams: CuteAFD 284.61 vs vLLM fork 267.61 tok/s = 1.06x (level)1.07x (1.06-1.12x)1 stream: median over 4 content cells 1.20x, cells 1.10-1.28x1 stream8K, prose, 1 stream: CuteAFD 99.08 vs vLLM fork 89.76 tok/s = 1.10x (faster)8K, code, 1 stream: CuteAFD 135.59 vs vLLM fork 111.65 tok/s = 1.21x (faster)8K, reasoning, 1 stream: CuteAFD 153.40 vs vLLM fork 119.51 tok/s = 1.28x (faster)8K, JSON, 1 stream: CuteAFD 120.25 vs vLLM fork 101.66 tok/s = 1.18x (faster)1.20x (1.10-1.28x)4 streams: median over 4 content cells 1.14x, cells 1.09-1.18x4 streams8K, prose, 4 streams: CuteAFD 176.28 vs vLLM fork 154.45 tok/s = 1.14x (faster)8K, code, 4 streams: CuteAFD 200.45 vs vLLM fork 184.44 tok/s = 1.09x (faster)8K, reasoning, 4 streams: CuteAFD 216.78 vs vLLM fork 183.90 tok/s = 1.18x (faster)8K, JSON, 4 streams: CuteAFD 200.04 vs vLLM fork 175.16 tok/s = 1.14x (faster)1.14x (1.09-1.18x)1 stream: median over 2 content cells 1.19x, cells 1.17-1.21x1 stream32K, prose, 1 stream: CuteAFD 64.71 vs vLLM fork 55.55 tok/s = 1.17x (faster)32K, code, 1 stream: CuteAFD 76.20 vs vLLM fork 63.12 tok/s = 1.21x (faster)1.19x (1.17-1.21x)4 streams: median over 2 content cells 1.12x, cells 1.12-1.12x4 streams32K, prose, 4 streams: CuteAFD 88.81 vs vLLM fork 79.28 tok/s = 1.12x (faster)32K, code, 4 streams: CuteAFD 96.69 vs vLLM fork 86.35 tok/s = 1.12x (faster)1.12x (1.12-1.12x)1 stream: median over 2 content cells 1.19x, cells 1.18-1.20x1 stream128K, prose, 1 stream: CuteAFD 26.59 vs vLLM fork 22.58 tok/s = 1.18x (faster)128K, code, 1 stream: CuteAFD 28.35 vs vLLM fork 23.64 tok/s = 1.20x (faster)1.19x (1.18-1.20x)

How to use it. Find the row for your prompt length and number of requests at once; the grey band is the noise band stated above.

Table view: the exact numbers
PromptContentStreamsvLLM fork, tok/sCuteAFD, tok/sCuteAFD ÷ vLLM forkReading
1Kprose1110.03121.231.10xfaster
1Kcode1141.75162.211.14xfaster
1Kreasoning1157.15199.711.27xfaster
1KJSON1125.67138.361.10xfaster
1Kprose4222.21237.471.07xlevel
1Kcode4280.17297.321.06xlevel
1Kreasoning4289.58323.211.12xfaster
1KJSON4267.61284.611.06xlevel
8Kprose189.7699.081.10xfaster
8Kcode1111.65135.591.21xfaster
8Kreasoning1119.51153.401.28xfaster
8KJSON1101.66120.251.18xfaster
8Kprose4154.45176.281.14xfaster
8Kcode4184.44200.451.09xfaster
8Kreasoning4183.90216.781.18xfaster
8KJSON4175.16200.041.14xfaster
32Kprose155.5564.711.17xfaster
32Kcode163.1276.201.21xfaster
32Kprose479.2888.811.12xfaster
32Kcode486.3596.691.12xfaster
128Kprose122.5826.591.18xfaster
128Kcode123.6428.351.20xfaster

Caveats

More: t/CAVEATS.md, the drift check drift/RESULTS-DRIFT.md, the K4 per-cell readings t/t-compare.json.

K4 at 8 and 16 streams (follow-up K4f)

The frozen K4 grid stopped at 4 streams; this follow-up ran the cells both engines admit, outside the protocol, with the same prompts and seeds.

Design FOLLOWUPS-K4f.md (declared before any request). The cells the frozen grid dropped that both engines admit, on the protocol's Block T prompts, seeds and nonce salt; one serving launch per arm; no request errors. Prompt-token counts identical except the 128K code prompts on CuteAFD (literal <think> text, as in the protocol).

Machine state. Drift subsets after the vLLM and CuteAFD side cells matched 2026-10-27: decode 0.95-1.03x on both engines; time to first token within 2% except one vLLM cell (1.12x).

Medians over content types and replicates; 1,024 output tokens per request; per-stream decode = tokens per second of one request; aggregate = all tokens finished per second.

Cell (input × streams)Decode per stream, tok/s (vLLM / CuteAFD / W8A16+amax)Aggregate, tok/sCuteAFD ÷ vLLM, aggregateFirst token, sCuteAFD ÷ vLLM, first token
1K × 852 / 58 / 58370 / 370 / 3691.001.52 / 2.84 / 2.951.87
1K × 1633 / 36 / 36322 / 465 / 4591.442.49 / 4.44 / 4.621.78
8K × 841 / 45 / 44224 / 235 / 2301.059.91 / 9.96 / 10.371.01
8K × 1624 / 26 / 26195 / 267 / 2621.3718.3 / 19.2 / 20.01.05
32K × 823 / 42 / 4393 / 101 / 981.0941.0 / 54.4 / 56.61.33
128K × 266 / 104 / 11225 / 29 / 281.1558.2 / 59.7 / 62.21.03

Reading (±8% band):

Files: t/V-side.json, t/C-side.json, t/C-w16amax-side.json, t/{V,C}-f-drift.json, K4f-cells.json.