Dominant open-source LLM serving engine (81K stars). PagedAttention + continuous batching + CUDA graphs deliver SOTA throughput. V1 engine runs scheduler out-of-process via ZMQ; supports 200+ model architectures, disaggregated P/D, 10+ quantization formats, multi-vendor GPU.
| Field | Value |
|---|---|
| Repo | |
| Primary language | Python (36.3M LOC), CUDA (2.4M), Rust (1.9M), C++ (1.7M) |
| License | Apache-2.0 |
| Stars / Contributors | 81,023 / 2,000+ |
| Version analyzed | v0.21.0 (2026-05-15) |
| Origin | UC Berkeley Sky Computing Lab (Woosuk Kwon, Ion Stoica, Hao Zhang) |
| Governance | Community-driven, multi-corporate backing |
One-line pitch: Easy, fast, and cheap LLM serving for everyone.
LLM inference wastes GPU memory and throughput due to two fundamental problems. First, static KV cache allocation wastes 60-80% of memory to internal fragmentation — each request pre-allocates the maximum possible KV cache regardless of actual usage, and freed memory cannot be reclaimed until the entire allocation is released. Second, without continuous batching, the system blocks on the longest-running request in a batch, leaving GPU cycles idle while shorter requests have already completed. These two problems compound: fragmented memory means fewer concurrent requests, and static batching means lower GPU utilization per request.
PagedAttention manages KV cache as fixed-size blocks (like OS virtual memory pages), enabling dynamic allocation, deallocation, and copy-on-write sharing. A block table provides virtual→physical indirection, allowing blocks to be non-contiguous in GPU memory. Continuous batching allows new requests to enter and completed requests to leave mid-batch — the scheduler re-evaluates the request pool at every decode step. The V1 engine runs the scheduler in a dedicated process (connected via ZMQ IPC with msgspec serialization) to avoid GIL contention between the CPU-bound scheduler and GPU-bound model execution.
PagedAttention's block-table indirection. The virtual→physical KV cache mapping enables COW prefix sharing, dynamic memory allocation, preemptive scheduling, and disaggregated serving (KV block transfer across nodes via NIXL). This single abstraction is what made continuous batching without memory waste practical. Every subsequent LLM serving system has adopted or reimplemented the idea — it is to LLM serving what virtual memory is to operating systems.
Near-zero KV cache memory waste (<4% fragmentation vs 60%+ with static allocation), 2-4× throughput improvement over static-batch baselines, and de facto standard status for open-source LLM serving (81K GitHub stars, 200+ supported architectures, 2000+ contributors).
Top modules by centrality:
| Module | Purpose |
|---|---|
vllm/entrypoints/ | User-facing: LLM (offline), OpenAI API server (online), gRPC, Anthropic API, MCP |
vllm/v1/engine/ | EngineCore (scheduler + IPC), AsyncLLM, input/output processors |
vllm/v1/core/ | Scheduler, KV cache manager, block pool, prefix caching |
vllm/v1/worker/ | GPUWorker, GPUModelRunner, CUDA graph capture |
vllm/v1/attention/ | Attention backend registry (FlashAttention, FlashInfer, TRTLLM-GEN, FlashMLA, TOKENSPEED_MLA) |
vllm/model_executor/ | Model loading, weight management, 200+ architecture implementations |
vllm/model_executor/layers/ | NN building blocks: attention, linear, MoE, quantization wrappers |
vllm/distributed/ | TP / PP / EP / DP, allreduce, NCCL, KV transfer, EPLB |
csrc/ | C++/CUDA/HIP kernels: paged attention, quantization, sampling, MoE, allreduce |
vllm/platforms/ | Hardware abstraction: CUDA, ROCm, CPU, TPU, XPU, plugin system |
vllm/v1/spec_decode/ | Speculative decoding: EAGLE, n-gram, MTP, DFlash |
vllm/v1/structured_output/ | Constrained decoding: xgrammar, guidance, outlines, lm-format-enforcer |
vllm/multimodal/ | Multi-modal input processing (images, video, audio) |
vllm/config/ | VllmConfig dataclass hierarchy (100+ fields) |
rust/ | Rust-based tokenizer for high-perf text processing |
import vllm) #| Export | Role |
|---|---|
LLM | Offline batch inference (.generate(), .chat(), .enqueue()) |
SamplingParams | Generation parameter struct (temp, top_p, top_k, max_tokens, structured output) |
RequestOutput / CompletionOutput | Output containers |
EngineArgs | Engine configuration from CLI args |
AsyncLLMEngine / LLMEngine | Legacy engine interfaces (V0, maintained for compat) |
PoolingParams | Embedding / classification / scoring params |
ModelRegistry | Model architecture registration |
vllm serve — launch OpenAI-compatible API servervllm bench — benchmarkingvllm complete / vllm chat — interactive usage| Flag | Default | Effect |
|---|---|---|
--model | (required) | HuggingFace model name or path |
--tensor-parallel-size / -tp | 1 | Tensor parallelism degree |
--pipeline-parallel-size / -pp | 1 | Pipeline parallelism degree |
--gpu-memory-utilization | 0.92 | Fraction of GPU mem for KV cache |
--dtype | auto | Weight precision (float16/bfloat16/float32) |
--quantization | None | Quantization method (fp8, awq, gptq, …) |
--max-model-len | auto | Maximum sequence length |
--enforce-eager | False | Disable CUDA graphs + torch.compile |
--enable-prefix-caching | False | Automatic prefix caching |
--spec-method / --spec-model | None | Speculative decoding config |
vllm/plugins/): register out-of-tree hardware backends at runtimevllm/platforms/): subclass Platform for new hardware (TPU, Gaudi, Ascend, Spyre, etc.)AttentionBackend interfacedistributed/kv_transfer/): pluggable KV cache transport for disaggregated servingSamplingParams — vllm/sampling_params.py #msgspec.Struct (not dataclass) with omit_defaults=True for compact wire formatdict=True mixin enables dict-like access while retaining struct performance.VllmConfig — vllm/config/ #ModelConfig, CacheConfig, ParallelConfig, SchedulerConfig, LoRAConfig, QuantizationConfigArgs, etc.LLM constructor kwargs. Passed by reference to all engine components.EngineCoreRequest / EngineCoreOutput — vllm/v1/engine/__init__.py #(sequence_idx, position) → physical_block_id, managed by PagedAttention block managerRequest — vllm/v1/request.py #EngineCoreRequest, lives in scheduler's requests dict and waiting/running queues, destroyed on completion/abortLLM.generate() → tokens out #| Hop | Bottleneck | Dominant cost |
|---|---|---|
| IPC serialize/deserialize | CPU, msgspec | ~0.1 ms (zero-copy) |
Scheduler (schedule()) | CPU, single-thread Python | ~0.01–0.1 ms |
| Block manager | CPU | ~0.01 ms |
| Model forward (decode) | GPU, memory-bandwidth-bound | ~5–50 ms (model-size dependent) |
| Attention kernel | GPU VRAM bandwidth | major fraction of forward |
| Sampling | GPU (FlashInfer sampler) | ~0.1 ms |
| Detokenization | CPU | ~0.01 ms |
Prefill is compute-bound ($O(n^2)$ in sequence length for attention, $O(n)$ for FFN); decode is memory-bandwidth-bound (one token at a time reads full KV cache per layer).
README claims "state-of-the-art serving throughput." The architecture supports this via continuous batching + PagedAttention + CUDA graphs. The main tension point: the EngineCore monolith (core.py, ~89KB) is single-threaded Python — at extreme QPS (thousands of concurrent requests), scheduler CPU time could bottleneck before GPU saturates. The V1 engine mitigates this by running the scheduler in a dedicated process (eliminating GIL contention with model execution), but the single-threaded scheduler remains the theoretical ceiling.
无形式化作者证明 — 仅实证。
vLLM's claims are validated empirically through published benchmarks (the original SOSP'23 paper shows 2-4× throughput gains over baselines) and sustained community adoption (81K stars, adoption by major cloud providers). No formal correctness proofs exist for the scheduler, block manager, or attention kernel implementations. Memory safety relies on the block table invariant: every physical block is either free, uniquely assigned to one virtual block, or COW-shared with a positive reference count — but this invariant is enforced by runtime logic, not proven.
| Mechanism | Where | Why |
|---|---|---|
| Multi-process | EngineCore vs. workers | GIL avoidance: scheduler (CPU-bound Python) and model execution (GPU-bound C++ extensions) run in separate processes |
| ZMQ IPC | Engine ↔ worker boundary | Low-latency message passing with msgspec zero-copy serialization |
| CUDA streams | Model execution | Async GPU execution, overlap compute with memory transfers |
| CUDA/HIP graphs | Decode phase | Captured execution graphs eliminate kernel launch overhead |
| torch.compile | Model forward | Piecewise compilation for kernel fusion and graph-level optimization |
| Ray | Multi-node | Optional distributed executor for cross-node TP/PP |
| asyncio | API server | Async HTTP/SSE handling in FastAPI server process |
The V1 engine's key architectural insight: the EngineCore process runs the scheduler (pure Python, CPU-bound) while GPUWorker processes run model execution (mostly C++/CUDA extensions that release the GIL). The ZMQ IPC boundary is the price paid for process isolation — ~0.1ms per step via msgspec, much cheaper than GIL contention would be. The IPC uses msgspec Struct serialization rather than pickle, reducing overhead by 10-100×.
gpu_memory_utilization (default 0.92) controls the fraction reserved for KV cache after model weights and activations.cpu_offload_gb parameter for partial weight offloading to host memory.CUDAGraphDispatcher.| Mechanism | Benefit | Magnitude |
|---|---|---|
| PagedAttention | Near-zero KV cache fragmentation | <4% waste vs 60%+ static |
| Continuous batching | GPU never idles waiting for longest request | 2-4× throughput over static |
| Chunked prefill | Long prompts interleaved with decode | Reduces TTFT variance |
| Prefix caching (APC) | Shared KV blocks for common prefixes | Up to 2× throughput for shared-prefix workloads |
| CUDA/HIP graphs | Eliminate kernel launch overhead | 15-30% decode speedup |
| torch.compile | Automatic kernel fusion | Variable, model-dependent |
| Speculative decoding | Multiple tokens per step | 2-3× decode speedup (EAGLE/MTP) |
| Quantization (FP8/NVFP4/INT4) | Reduced memory + faster GEMM | 2-4× memory, 1.5-2× throughput |
| Disaggregated P/D | Separate prefill and decode pools | Optimizes for different compute profiles |
| Step | Claim | Evidence | Depends on |
|---|---|---|---|
| 1 | Static KV cache allocation wastes 60-80% of GPU memory to internal fragmentation | SOSP'23 paper §2: measured fragmentation on Llama-13B/OPT-30B workloads | — |
| 2 | Virtual memory–style paging (PagedAttention) reduces fragmentation to <4% | Block table indirection allows non-contiguous allocation; waste is at most block_size−1 tokens per sequence | Step 1 |
| 3 | Near-zero fragmentation → more concurrent requests → higher GPU utilization | More KV cache capacity means more sequences fit in memory simultaneously | Step 2 |
| 4 | Continuous batching exploits the freed capacity — new requests enter mid-batch as others complete | Scheduler re-evaluates every decode step; no idle GPU cycles waiting for batch stragglers | Steps 2, 3 |
| 5 | COW block sharing enables prefix caching and parallel sampling without memory duplication | Block table indirection makes COW a pointer update, not a data copy; APC shares common system prompts | Step 2 |
| 6 | Out-of-process scheduler eliminates GIL contention between CPU scheduling and GPU execution | V1 engine: EngineCore in separate process via ZMQ IPC; msgspec serialization costs ~0.1ms vs GIL contention measured at ms-scale | Steps 3, 4 |
| 7 | Combined system achieves 2-4× throughput over static-batch baselines and becomes the de facto open-source serving standard | 81K GitHub stars, 200+ models, 2000+ contributors; adopted by major cloud providers; biweekly releases with 200+ contributors per release | Steps 1-6 |
| Issue | Severity | Status |
|---|---|---|
core.py at ~89KB | High (maintainability) | Architectural — deliberate perf-over-readability trade-off |
Dual engine (V0 engine/ + V1 v1/engine/) | Medium | V0 maintained for compat only, V1 is default |
| 200+ individual model files | Medium (maintenance) | Each arch has its own impl; boilerplate accumulates |
| C++20 build requirement (v0.21.0) | Low | Driven by PyTorch upstream; breaks older GCC <10 |
| Transformers v4 deprecation | Low | Migration to v5 in progress |
| DeepSeek V4 separate sub-package | Low | vllm/models/deepseek_v4/ lives outside normal model registry |
requirements/build_rust.sh for tokenizer.buildkite/).github/)tests/benchmarks/ for offline and online throughput/latency| Dependency | Health | Risk |
|---|---|---|
| PyTorch | Actively maintained, tracked closely | C++20 requirement cascade |
| HuggingFace Transformers | v5 migration underway | Breaking API changes |
| FlashAttention / FlashInfer | Actively maintained | FlashAttention: NVIDIA-only |
| msgspec | Small but maintained | Low bus factor, critical on IPC path |
| xgrammar / guidance / outlines | Varying maturity | Fragmented structured output ecosystem |
| NCCL | NVIDIA-maintained | AMD equivalent (RCCL) tracked separately |
| Metric | Value |
|---|---|
| Commits per minor release | 367 (v0.21.0) |
| New contributors per release | 49 (v0.21.0) |
| Total contributors | 2,000+ |
| GitHub stars | 81,023 |
| Release cadence | ~biweekly minor releases with patch releases between |
| Origin | UC Berkeley Sky Computing Lab (Kwon, Stoica, Zhang) |
| Governance | Community-driven, multi-corporate participation |
| Communication | GitHub Issues, vLLM Forum (discuss.vllm.ai), Developer Slack (slack.vllm.ai) |
| Bus factor | High — 202 contributors in a single release, core team spans multiple organizations |
| AI agent integration | AGENTS.md and CLAUDE.md at repo root for AI-assisted development |
| Dimension | vLLM | TensorRT-LLM | SGLang | TGI (HuggingFace) |
|---|---|---|---|---|
| Language | Python + C++/CUDA | C++ + Python | Python + C++ | Rust + Python |
| Model support | 200+ archs | ~30 | ~50 | ~60 |
| Hardware | NVIDIA, AMD, CPU, TPU, 7+ plugins | NVIDIA only | NVIDIA, AMD | NVIDIA, AMD |
| Memory mgmt | PagedAttention | Paged KV cache | RadixAttention | PagedAttention |
| Peak perf (NVIDIA) | Very high | Highest | Very high | High |
| Quantization | FP8/NVFP4/MXFP4/INT8/INT4/GPTQ/AWQ/GGUF | FP8/INT8/INT4 | FP8/INT8/AWQ | GPTQ/AWQ/BNB |
| Structured output | 4 backends | Limited | 1 backend | 1 backend |
| Disaggregated P/D | Yes (NIXL) | Yes | Yes | No |
| Spec decode | EAGLE/n-gram/MTP/DFlash | Draft model | EAGLE | No |
| API compat | OpenAI + Anthropic + gRPC + MCP | Triton Inference Server | OpenAI | OpenAI |
| Ease of install | pip install vllm | Docker + TensorRT | pip install | Docker |
| License | Apache-2.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 |
| Community | 81K stars, 2K+ contrib | ~16K stars | ~25K stars | ~10K stars |
Winner by scenario:
| Component | File | Role |
|---|---|---|
| Offline entrypoint | vllm/entrypoints/llm.py | LLM.__init__ — builds EngineArgs → VllmConfig → LLMEngine |
| V1 LLMEngine | vllm/v1/engine/llm_engine.py | LLMEngine.__init__ — creates InputProcessor, OutputProcessor, EngineCore client |
| EngineCore | vllm/v1/engine/core.py | Monolithic scheduler loop — schedule, dispatch, collect outputs (~89KB) |
| V1 Scheduler | vllm/v1/core/sched/scheduler.py | Scheduler.schedule() — request admission, token budget, block allocation |
| KV Cache Manager | vllm/v1/core/ | Block pool management, prefix caching, COW logic |
| GPU Model Runner | vllm/v1/worker/gpu_model_runner.py | execute_model() — builds inputs, runs forward, samples, returns tokens |
| CUDA Graph Dispatcher | vllm/v1/cudagraph_dispatcher.py | Selects pre-captured graph by batch size |
| OpenAI API Server | vllm/entrypoints/openai/api_server.py | FastAPI app, build_async_engine_client(), routes for /v1/completions, /v1/chat/completions |
| Paged Attention Kernels | csrc/attention/ | C++/CUDA paged attention v1/v2/MLA kernels |
| Quantization Kernels | csrc/quantization/ | FP8, INT8, INT4, GPTQ, AWQ CUDA kernels |
| MoE Kernels | csrc/moe/ | Fused MoE, topk selection |
| Sampling Kernel | csrc/sampler.cu | GPU-side sampling |
| KV Transfer | vllm/distributed/kv_transfer/ | Disaggregated P/D connectors (NIXL, etc.) |
| Platform Abstraction | vllm/platforms/ | CUDA, ROCm, CPU, TPU, XPU dispatch |
| Model Registry | vllm/model_executor/models/ | 200+ model architecture implementations |
| Config Hierarchy | vllm/config/ | VllmConfig and all sub-configs |
SamplingParams and EngineCoreRequest/Output use msgspec.Struct instead of dataclasses. This enables zero-copy serialization across the ZMQ IPC boundary, avoiding the 10-100× overhead of pickle. The choice of omit_defaults=True further reduces wire size for the common case where most sampling parameters are left at defaults. This design decision is load-bearing — switching to pickle would measurably increase per-step latency and could make the IPC boundary the bottleneck at high QPS.vllm/v1/engine/core.py packs the entire scheduling loop into one ~89KB file to minimize cross-module function call overhead on the hot path. Python function calls across modules involve dict lookups and frame creation that are measurable at thousands of scheduling decisions per second. This is a deliberate performance-over-readability trade-off that trades maintainability for ~microseconds per step.CUDAGraphDispatcher pre-captures CUDA execution graphs for multiple batch sizes at startup (during capture_model()). At runtime it selects the smallest graph that fits the current batch, avoiding the 15-30% decode overhead of eager execution. The batch-size set is determined by profiling during profile_run(), which measures maximum KV cache capacity.core.py: the ~89KB monolith is the project's biggest maintainability risk. Extracting the scheduler, request state machine, and IPC handling into separate modules would improve testability without meaningful perf regression (the IPC boundary already forces serialization).gpu_memory_utilization=0.92 is aggressive — will OOM on GPUs shared with other processes. Lower to 0.80–0.85 in shared environments.enforce_eager=True kills performance — disables CUDA graphs and torch.compile. Only use for debugging.max_model_len auto-detection — reads from model config, which can be 128K+ for long-context models. Will OOM on memory-constrained GPUs. Set explicitly.--enable-prefix-caching must be set explicitly. For workloads with shared system prompts this can double throughput.