mini-vLLM
A from-scratch LLM inference engine. It builds the two systems ideas behind vLLM: continuous batching and a paged KV-cache. It serves an OpenAI-compatible API, and it is checked token for token against Hugging Face transformers.
- 325 tok/s
- mini-vLLM with all 8 prompts in one batch, on a T4 GPU
- 42 tok/s
- Hugging Face
generate(), one prompt at a time, same prompts - 50 of 50
- GPU tests pass, checked against Hugging Face
- 4× smaller
- weights with INT4, at 0.98 cosine similarity
How it works
Continuous batching
Standard batching waits for a full batch, then releases the whole batch when the slowest sequence finishes. That wastes GPU time whenever sequences differ in length. Continuous batching runs a decode step every tick. New sequences join, and finished ones leave, without stalling the rest. The scheduler decides at each step which sequences run, which wait, and which get preempted under memory pressure. A preempted sequence has its blocks freed, and it is re-prefilled from its prompt and the tokens generated so far when it is admitted again.
Paged KV-cache
The key and value tensors that every attention layer accumulates grow with sequence length. A contiguous buffer per sequence fragments memory and caps the batch size. The paged cache works like virtual memory in an operating system: a fixed pool of physical blocks, each holding a set number of token slots, and a block table per sequence that maps positions to blocks. Sequences of very different lengths share one pool without fragmentation. On CUDA, a custom Triton kernel does the paged attention.
The pieces
- API layer.
POST /v1/completionsin FastAPI, with streaming. - AsyncLLMEngine. One background task steps the engine and sends tokens to each request.
- LLMEngine. A scheduler that admits and preempts at every step, and a block manager that owns the pool of physical blocks.
- Runner. A dense KV cache for CPU and tests, or the paged runner with the Triton kernel for Llama models on CUDA.
- Model and weights. TinyLlama-1.1B and GPT-2.
Results
All GPU numbers come from a Kaggle T4 (16 GB) with TinyLlama-1.1B in fp16. The benchmarks were last re-run on 8 October 2026.
Throughput against Hugging Face
Under concurrent load
Quantization
Model size
Decode speed
Correctness
Decoding is checked token for token against Hugging Face transformers. For quantization, the check is a calibrated error bound. All 50 tests pass on the GPU, with none skipped. On a CPU, 39 pass and 11 are skipped, because the Triton kernel and the real-model paged decode need CUDA.
| Suite | Tests | What it shows |
|---|---|---|
| Dense runner | 3 of 3 | Single, batched and continuous-batch decode match model.generate() exactly. |
| Block manager, scheduler, paged attention | 23 of 23 | Block allocation, preemption under memory pressure, and paged attention (with grouped-query heads) match dense attention. |
| Paged runner on a real model | 4 of 4 | The full paged decode path matches Hugging Face on the GPU. Batched sampling equals per-sequence sampling. |
| Quantization | 6 of 6 | INT8 and INT4 round trips and model-level error bounds hold. |
| API server | 8 of 8 | Streaming equals non-streaming. Concurrent requests match solo runs. Bad input is rejected. Stop strings cut the output. |
| Engine robustness | 6 of 6 | Recompute after preemption matches an unconstrained run. Aborts and engine failures are handled. |
What these numbers do not show
- All results come from one GPU and one small model, TinyLlama-1.1B.
- The decode path still loops over the model's 22 layers in Python, and prefill still uses the dense Hugging Face forward pass. Neither is profiled yet.
- Where the speed-up from the last round of changes comes from has not been measured one change at a time.
- The first run in a fresh process is much slower than the rest, so the benchmark scripts do an untimed warm-up first.
Watch the scheduler work
This is mini-vLLM's own scheduling code: the continuous-batching scheduler, the paged KV-cache block manager and the engine step, ported line by line to JavaScript. A test checks the port step by step against traces of the Python engine. Only the model is left out: each step, every running sequence gets one token.
KV-cache block pool
Waiting (first in line on the left)
Running batch
Timeline
Each row is a request, each column a step. Grey: waiting. Colour: running. Red: preempted (its blocks were freed and it waits to recompute).
Add your own request
Stream from your own server
The engine needs a GPU (or a CPU with GPT-2), so this page cannot run the model itself. Start the server on your machine, connect, and send several requests at once to watch continuous batching: each request streams on its own lane, with its own time to first token.
Start the server
pip install -e .
MINI_VLLM_MODEL=gpt2 MINI_VLLM_DEVICE=cpu \
MINI_VLLM_CORS_ORIGINS=https://shlokkvaishnav.github.io \
uvicorn mini_vllm.api.server:app --port 8000
MINI_VLLM_CORS_ORIGINS lets this page call the server. Your browser can ask for permission to reach a local address. Leave out the GPT-2 settings to serve TinyLlama on a GPU.
Not connected.