LLM/multimodal serving engine (28K stars). Three-process ZMQ architecture (Tokenizer→Scheduler→Detokenizer) with RadixAttention prefix tree, speculative decoding zoo (EAGLE/MTP/DFLASH), HiCache offloading, and 7+ hardware backends. Dual identity: frontend DSL + high-perf runtime.
| Field | Value |
|---|---|
| Repo | |
| Primary language | Python (39M LOC), Rust (4.2M), CUDA (2.3M), C++ (1.6M) |
| License | Apache-2.0 |
| Stars | 28,266 |
| Version analyzed | v0.5.12 (2026-05-16) |
| Origin | LMSYS / UC Berkeley (Lianmin Zheng, Ying Sheng, Liangsheng Yin) |
| Sponsor / governance | Non-profit LMSYS; multi-corporate adoption (xAI, AMD, NVIDIA, Cursor, etc.) |
One-line pitch: Low-latency, high-throughput serving for LLMs and multimodal models from single-GPU to multi-node clusters.
LLM serving workloads exhibit massive prefix overlap — system prompts, few-shot examples, and multi-turn conversation histories are recomputed from scratch for every request in conventional serving systems. This wastes both GPU compute (redundant prefill) and memory (duplicate KV cache entries). At production scale with thousands of concurrent requests sharing common prefixes, this overhead compounds into a throughput ceiling that naive continuous-batching cannot break through. Additionally, the Python GIL creates contention between CPU-bound scheduling and GPU-bound model execution, and single-hardware backends limit deployment flexibility.
RadixAttention organizes the KV cache as a radix tree (trie) keyed by token sequences, enabling automatic prefix sharing across requests without explicit user intervention. When a new request arrives, the tree is traversed to find the longest matching prefix — only the unmatched suffix requires new prefill computation. The tree supports LRU eviction, and its unified variant (UnifiedRadixTree) extends to sliding-window attention models and disaggregated decode scenarios.
The three-process architecture separates concerns via ZMQ IPC: TokenizerManager (main process) handles request tokenization and routing, Scheduler (subprocess) runs batch formation and GPU worker dispatch, DetokenizerManager (subprocess) handles token-to-text streaming. This eliminates GIL contention entirely — each process has its own GIL.
The runtime supports a speculative decoding zoo (EAGLE v1/v2/v3, MTP, DFLASH, N-gram, custom user-registered algorithms) integrated with CUDA graph capture and the radix cache, plus dedicated kernel backends per hardware platform (NVIDIA CUDA through GB300, AMD ROCm MI300/MI355, Intel XPU, Google TPU via JAX, Ascend NPU, Apple Silicon via MLX).
The radix tree KV cache. Organizing prefix cache as a trie indexed by token-id sequences provides $O(L)$ prefix lookup (where $L$ is sequence length), enables implicit sharing without user annotation, and naturally handles mixed-length multi-turn conversations. The LRU eviction policy operates at tree-node granularity, reclaiming memory from least-recently-used prefix subtrees. This single data structure — effectively an OS-style page cache for KV memory, indexed by content rather than address — is what separates SGLang's caching story from block-table approaches: it captures semantic structure (shared prefixes) rather than just reducing fragmentation.
Up to 5× faster inference from RadixAttention prefix sharing on common-prefix workloads. 7× faster DeepSeek MLA serving (v0.3). Deployed on 400,000+ GPUs in production across xAI, AMD, NVIDIA, Cursor, major cloud providers, and academic institutions. Biweekly releases, active RL/post-training backbone adoption (AReaL, verl, etc.).
Top modules by centrality:
| Module | Purpose |
|---|---|
python/sglang/srt/managers/scheduler.py | Core scheduling loop: batch formation, prefill/decode dispatch, 6+ mixins for parallelism modes |
python/sglang/srt/entrypoints/engine.py | Engine class: orchestrates three-process architecture via ZMQ |
python/sglang/srt/mem_cache/radix_cache.py | RadixAttention prefix tree — the differentiating data structure |
python/sglang/srt/mem_cache/unified_radix_cache.py | Extended radix tree with HiCache (CPU/SSD offload) |
python/sglang/srt/managers/tp_worker.py | Tensor-parallel model worker — bridges scheduler to GPU |
python/sglang/srt/layers/attention/ | Attention backends: FlashInfer, FA3, FA4, MLA, Mamba |
python/sglang/srt/layers/moe/ | MoE layers: DeepEP, FusedMoE, MegaMoE |
python/sglang/srt/speculative/ | Speculative decoding: EAGLE, MTP, DFLASH, N-gram |
python/sglang/srt/disaggregation/ | Prefill-decode disaggregation: NIXL, Mooncake, MORI |
sgl-kernel/ | Custom CUDA/C++/Metal kernels, cross-platform builds |
python/sglang/srt/server_args.py | All CLI arguments (~340KB) — the configuration surface |
python/sglang/srt/models/ | Model architectures: Llama, Qwen, DeepSeek, Gemma, etc. |
python/sglang/lang/ | Frontend DSL: gen, select, function, backend connectors |
python/sglang/srt/platforms/ | Hardware abstraction: CUDA, ROCm, NPU, MLX, CPU |
import sglang) #| Export | Role |
|---|---|
Engine | Primary inference engine (offline + online): .generate(), .encode(), .rerank() |
Runtime | Legacy runtime wrapper |
gen, select, function | Frontend DSL for structured LLM programs |
RuntimeEndpoint | Backend connector to a running SGLang server |
OpenAI, Anthropic, VertexAI, LiteLLM | Third-party backend connectors (lazy-imported) |
ServerArgs | Engine configuration (lazy-imported, ~340KB of CLI arguments) |
assistant, user, system | Chat template helpers for DSL |
python -m sglang.launch_server — launch the HTTP serverpython -m sglang.bench_serving — online serving benchmarkpython -m sglang.bench_one_batch — single-batch latencypython -m sglang.bench_offline_throughput — offline throughputpython -m sglang.auto_benchmark — auto-tuning driver| Flag | Default | Effect |
|---|---|---|
--model-path | (required) | HuggingFace model name or local path |
--tp-size | 1 | Tensor parallelism degree |
--dp-size | 1 | Data parallelism degree |
--mem-fraction-static | auto | Fraction of GPU memory for KV cache |
--chunked-prefill-size | auto | Chunk size for long-prompt interleaving with decode |
--quantization | None | Quantization method (fp8, fp4, awq, gptq, etc.) |
--max-running-requests | auto | Maximum concurrent decoding requests |
--schedule-policy | "fcfs" | Scheduling policy (FCFS, priority, LoRA-aware) |
--enable-overlap-schedule | False | Pipelined CPU↔GPU overlap scheduling |
--speculative-algorithm | None | Speculative decoding method (eagle, mtp, dflash, ngram) |
srt/plugins/): register out-of-tree extensions at runtime via load_plugins()srt/platforms/, srt/hardware_backend/): subclass for new accelerators (NPU, MLX already implemented)srt/layers/attention/): pluggable kernel implementations (FlashInfer, FA3, FA4, MLA, Mamba)srt/speculative/): custom user-registered spec-decode methods via the algorithm registrylang/backend/): connect the DSL to any LLM API (OpenAI, Anthropic, VertexAI, custom)srt/disaggregation/): pluggable transport for disaggregated P/D (NIXL, Mooncake, MORI)srt/layers/moe/): pluggable expert dispatch (DeepEP, FusedMoE, MegaMoE, FlashInfer CuteDSL)Req / ScheduleBatch — srt/managers/schedule_batch.py #Req is a dataclass tracking per-request state (prompt tokens, output tokens, sampling params, KV cache indices, stop conditions, LoRA path). ScheduleBatch aggregates requests for a single forward pass with batched metadata tensors.Req created when TokenizerManager dispatches to Scheduler, lives in waiting_queue → running_batch, destroyed on completion/abort. ScheduleBatch created fresh each scheduling step.RadixCache — srt/mem_cache/radix_cache.py #UnifiedRadixTree — srt/mem_cache/unified_radix_cache.py #offload() (move cold KV from GPU to CPU/SSD) and reload() (bring offloaded KV back to GPU on cache hit).MemoryPool — srt/mem_cache/memory_pool.py #mem_fraction_static and model's per-token KV size.GenerateReqInput — srt/managers/io_struct.py #ForwardMode — srt/model_executor/forward_batch_info.py #ScheduleBatch each step.Engine.generate() → tokens out #| Hop | Bottleneck | Dominant cost |
|---|---|---|
| Tokenization | CPU, HF tokenizer | ~0.1 ms (amortized, first step only) |
| ZMQ IPC (TM→Scheduler) | CPU, serialization | ~0.1 ms |
| Radix cache lookup | CPU, trie traversal | ~0.01 ms |
| Schedule + batch formation | CPU, single-thread Python | ~0.01–0.1 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 | ~0.1 ms |
| ZMQ IPC (Scheduler→DET) | CPU | ~0.1 ms |
| Detokenization | CPU, incremental | ~0.01 ms |
Prefill is compute-bound ($O(n^2)$ for attention, $O(n)$ for FFN); decode is memory-bandwidth-bound (reads full KV cache per layer for one new token).
README claims "zero-overhead CPU scheduler." The three-process architecture does eliminate GIL contention, but the Scheduler itself is single-threaded Python with 6+ mixin classes composing behavior at runtime. At extreme QPS, the Scheduler's per-step overhead scales linearly with batch size (radix cache updates, batch metadata construction). The overlap scheduler (batch_overlap/) mitigates this by pipelining CPU scheduling work with GPU execution, but the single-threaded Python ceiling remains the theoretical throughput limit. The server_args.py at ~340KB reflects a configuration surface that has outgrown simple CLI management.
无形式化作者证明 — 仅实证。
SGLang's claims are validated empirically through published benchmarks (original RadixAttention paper: up to 5× speedup from prefix sharing; v0.3 blog: 7× faster DeepSeek MLA) and demonstrated production adoption (400K+ GPUs, major cloud providers). No formal correctness proofs exist for the scheduler, radix cache eviction policy, or attention kernel implementations. The radix cache invariant — every KV block referenced by a trie node is either valid in the GPU memory pool or correctly offloaded to CPU/SSD with reload capability — is enforced by runtime logic, not proven. Memory safety relies on single-writer semantics: only the Scheduler subprocess mutates the cache.
| Mechanism | Where | Why |
|---|---|---|
| Multi-process | TokenizerManager / Scheduler / DetokenizerManager | GIL avoidance: each process has its own GIL; CPU scheduling and GPU execution never contend |
| ZMQ IPC | Between all three processes | Low-latency message passing between processes on the same node |
| CUDA streams | TpModelWorker | Async GPU execution, overlap compute with memory transfers |
| CUDA graphs | Decode phase | Captured execution graphs eliminate kernel launch overhead; piecewise graphs for flexibility |
| torch.compile | Model forward | JIT compilation for kernel fusion |
| Data parallel controller | Multi-GPU | Distributes requests across DP-rank schedulers |
| Ray | Multi-node | Optional distributed deployment for cross-node parallelism |
| asyncio | HTTP server (uvicorn/FastAPI) | Async HTTP handling in the main process |
Three separate OS processes communicate exclusively via ZMQ IPC. The TokenizerManager runs in the main process alongside the HTTP server (both doing I/O-bound work). The Scheduler runs in a dedicated subprocess doing CPU-bound scheduling. The DetokenizerManager runs in another subprocess doing lightweight CPU work. No process needs the other's GIL. This is more aggressive than vLLM's V1 design (two-process: entrypoint + EngineCore) — SGLang adds a third process for detokenization.
UnifiedRadixTree tracks block residency across all three tiers.mem_fraction_static controls the fraction of GPU memory reserved for KV cache after model weights and activations.self, creating a complex implicit dependency graph. No formal lock hierarchy — safety relies on single-threaded execution within the Scheduler subprocess.| Mechanism | Benefit | Magnitude |
|---|---|---|
| RadixAttention prefix tree | Automatic prefix sharing, no redundant prefill | Up to 5× for shared-prefix workloads |
| Continuous batching | No idle GPU cycles waiting for batch stragglers | 2-4× over static batching |
| Chunked prefill | Long prompts interleaved with decode | Reduces TTFT variance |
| HiCache (GPU→CPU→SSD) | Cold KV offloaded, more active requests fit in GPU | Extended effective KV capacity |
| HiSparse (sparse MLA) | Only active KV heads in GPU memory | Reduced MLA memory footprint |
| CUDA graphs (piecewise) | Eliminate kernel launch overhead | 15-30% decode speedup |
| Speculative decoding (EAGLE/MTP/DFLASH) | Multiple tokens per step | 2-3× decode speedup |
| Quantization (FP4/FP8/INT4/AWQ/GPTQ) | Reduced memory + faster GEMM | 2-4× memory, 1.5-2× throughput |
| Overlap scheduling | CPU scheduling hidden behind GPU execution | Reduced per-step latency |
| Disaggregated P/D (NIXL/Mooncake/MORI) | Separate prefill and decode GPU pools | Optimizes for different compute profiles |
set_mla_kv_buffer delivering 12× speedup| Step | Claim | Evidence | Depends on |
|---|---|---|---|
| 1 | LLM serving workloads have massive prefix overlap (system prompts, few-shot examples, multi-turn history) | Empirical: RadixAttention paper measures 30-80% prefix sharing ratio across chat, coding, and multi-turn workloads | — |
| 2 | A radix-tree (trie) indexed by token sequences enables $O(L)$ automatic prefix matching and subtree eviction | Data-structure property: trie traversal is proportional to key length; LRU eviction prunes entire subtrees atomically | Step 1 |
| 3 | Prefix sharing eliminates redundant prefill computation, translating shared-prefix ratios directly into throughput gains | Up to 5× speedup measured on shared-prefix benchmarks; GPU compute saved is proportional to the prefix hit ratio | Step 2 |
| 4 | Three-process ZMQ architecture eliminates GIL contention between CPU scheduling and GPU execution | Each process has its own GIL; measured zero-overhead CPU scheduling vs GIL-constrained single-process designs | — |
| 5 | Speculative decoding (EAGLE/MTP/DFLASH) produces multiple tokens per step, amortizing the memory-bandwidth cost of decode | 2-3× decode speedup measured; overlap scheduling (Spec V2) hides CPU overhead of draft-verify pipelining | Step 4 |
| 6 | HiCache hierarchical offloading extends effective KV capacity beyond GPU memory without proportional latency penalty | GPU→CPU→SSD tiering keeps hot KV on GPU, cold KV on CPU/SSD; reload latency amortized by prefetching | Steps 2, 3 |
| 7 | Combined system achieves production-scale deployment and sustained community growth | 400K+ GPUs in production, 28K GitHub stars, biweekly releases, RL backbone adoption by AReaL/verl/Miles | Steps 1-6 |
| Issue | Severity | Status |
|---|---|---|
server_args.py at ~340KB | High (configuration explosion) | Growing with each release; no structured config hierarchy |
| Scheduler mixin explosion (6+ mixins) | High (maintainability) | Each parallelism mode adds a mixin; implicit cross-mixin state dependencies |
| Dual identity (frontend DSL + runtime) | Medium | Runtime complexity dwarfs DSL; lang/ largely orphaned relative to srt/ |
| Per-hardware kernel builds (5+ setup.py variants) | Medium | setup_rocm.py, setup_metal.py, setup_musa.py, CMakeLists.txt — fragmented build system |
| Model architecture files (50+) | Medium | Each model has its own impl; considerable boilerplate |
| 39M LOC Python | Low-Medium | Includes vendored docs (4M MDX), but core codebase is still enormous |
sgl-kernel/: CMake + setuptools for CUDA kernels; separate setup_rocm.py, setup_metal.py, setup_musa.py for other platformsrust/sglang-grpc/: Cargo for Rust gRPC serverproto/: Protobuf definitions for gRPC interfacedocker/sgl-kernel published as a separate PyPI packagetest/: Integration and end-to-end testspython/sglang/test/: Test utilities and helperssgl-kernel/tests/: Kernel unit testssgl-kernel/benchmark/: Kernel microbenchmarksbenchmark/: Top-level benchmark scripts and configs| Dependency | Health | Risk |
|---|---|---|
| PyTorch | Actively maintained, tracked closely (2.9→2.11 in recent releases) | Major version bumps cascade build requirements |
| FlashInfer | Actively maintained (0.6.11.post1), core attention backend | SGLang depends heavily on FlashInfer for MLA + MoE kernels |
| DeepEP | CUDA 13 migration | Tight coupling to DeepSeek-specific expert parallelism |
| Mooncake | External dependency for SSD offload in HiCache | Separate project, integration complexity |
| NIXL | KV transfer for disaggregation | Relatively new, stability maturing |
| HuggingFace Transformers | Model config loading | API churn across major versions |
| Metric | Value |
|---|---|
| GitHub stars | 28,266 |
| License | Apache-2.0 |
| Release cadence | Biweekly minor releases (v0.5.10 → v0.5.11 → v0.5.12 in ~4 weeks) |
| Origin | LMSYS / UC Berkeley |
| Governance | Non-profit LMSYS organization |
| Key contributors | Lianmin Zheng, Ying Sheng, Liangsheng Yin + community |
| Enterprise adoption | xAI, AMD, NVIDIA, Intel, LinkedIn, Cursor, Oracle Cloud, Google Cloud, Azure, AWS |
| RL/post-training adoption | AReaL, Miles, slime, Tunix, verl |
| Ecosystem | Joined PyTorch Ecosystem (2025/03), a16z open-source AI grant (2025/06) |
| Bus factor | Moderate — core team is LMSYS-affiliated, but broad corporate contributor base |
| Communication | GitHub Issues, LMSYS blog, official documentation site (docs.sglang.io) |
| Dimension | SGLang | vLLM | TensorRT-LLM | TGI (HuggingFace) |
|---|---|---|---|---|
| Language | Python + C++/CUDA + Rust | Python + C++/CUDA + Rust | C++ + Python | Rust + Python |
| Model support | ~50 architectures | 200+ architectures | ~30 | ~60 |
| Hardware | NVIDIA, AMD, TPU, NPU, MLX, CPU (7+ backends) | NVIDIA, AMD, CPU, TPU, XPU | NVIDIA only | NVIDIA, AMD |
| Memory mgmt | RadixAttention (prefix trie) | PagedAttention (block table) | Paged KV cache | PagedAttention |
| Prefix caching | Automatic (trie-based, zero annotation) | Opt-in (--enable-prefix-caching) | Limited | Limited |
| Process model | 3-process (Tok+Sched+Detok) | 2-process (V1: Entrypoint+EngineCore) | Single process | Single process |
| Peak perf (NVIDIA) | Very high | Very high | Highest | High |
| Spec decode | EAGLE v1/v2/v3, MTP, DFLASH, N-gram, custom | EAGLE, n-gram, MTP, DFlash | Draft model | No |
| Structured output | 1 backend (grammar) | 4 backends | Limited | 1 backend |
| Disaggregated P/D | NIXL + Mooncake + MORI | NIXL | Yes | No |
| Frontend DSL | gen/select/function (structured LLM programs) | None | None | None |
| MoE support | DeepEP, elastic EP, EPLB, MegaMoE | EP, EPLB | Limited EP | No |
| Quantization | FP4/FP8/INT4/AWQ/GPTQ/NVFP4 | FP8/NVFP4/MXFP4/INT8/INT4/GPTQ/AWQ/GGUF | FP8/INT8/INT4 | GPTQ/AWQ/BNB |
| API compat | OpenAI + gRPC | OpenAI + Anthropic + gRPC + MCP | Triton Inference Server | OpenAI |
| License | Apache-2.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 |
| Community | 28K stars | 81K stars, 2K+ contrib | ~16K stars | ~10K stars |
Winner by scenario:
| Component | File | Role |
|---|---|---|
| Engine entry point | python/sglang/srt/entrypoints/engine.py | Engine.__init__ — orchestrates three-process launch via ZMQ |
| HTTP server | python/sglang/srt/entrypoints/http_server.py | FastAPI/uvicorn OpenAI-compatible endpoints |
| Scheduler | python/sglang/srt/managers/scheduler.py | Core scheduling loop: 6+ mixins, batch formation, GPU dispatch |
| TokenizerManager | python/sglang/srt/managers/tokenizer_manager.py | Request tokenization, routing to scheduler |
| DetokenizerManager | python/sglang/srt/managers/detokenizer_manager.py | Token-to-text streaming output |
| TP worker | python/sglang/srt/managers/tp_worker.py | Tensor-parallel model forward |
| Schedule batch | python/sglang/srt/managers/schedule_batch.py | ScheduleBatch and Req dataclasses |
| IO structs | python/sglang/srt/managers/io_struct.py | GenerateReqInput, EmbeddingReqInput, IPC message types |
| Radix cache | python/sglang/srt/mem_cache/radix_cache.py | RadixAttention prefix tree |
| Unified radix cache | python/sglang/srt/mem_cache/unified_radix_cache.py | Extended tree + HiCache (CPU/SSD offload) |
| Memory pool | python/sglang/srt/mem_cache/memory_pool.py | GPU KV cache block allocator |
| KV cache builder | python/sglang/srt/mem_cache/kv_cache_builder.py | Pool construction at startup |
| Attention backends | python/sglang/srt/layers/attention/ | FlashInfer, FA3, FA4, MLA, Mamba |
| MoE layers | python/sglang/srt/layers/moe/ | DeepEP, FusedMoE, MegaMoE |
| Speculative decoding | python/sglang/srt/speculative/ | EAGLE, MTP, DFLASH, N-gram |
| Disaggregation | python/sglang/srt/disaggregation/ | NIXL, Mooncake, MORI transfer engines |
| Server args | python/sglang/srt/server_args.py | ~340KB: all CLI arguments and configuration |
| Public API | python/sglang/__init__.py | DSL exports + lazy runtime imports |
| Frontend DSL | python/sglang/lang/api.py | gen, select, function, etc. |
| Custom kernels | sgl-kernel/csrc/ | C++/CUDA kernel sources |
| Rust gRPC | rust/sglang-grpc/ | Rust gRPC server implementation |
| Global config | python/sglang/global_config.py | Global configuration singleton |
| Platforms | python/sglang/srt/platforms/ | Hardware abstraction (CUDA, ROCm, NPU, MLX, CPU) |
RadixCache evicts by pruning LRU leaf nodes and propagating upward when internal nodes become empty. This means an entire unused prefix branch (potentially thousands of tokens of shared KV) is reclaimed in one sweep, rather than block-by-block. The eviction decision is made at the trie level, not the memory-pool level, which keeps the hot working set in GPU memory even under extreme memory pressure. This is the key difference from block-table approaches where eviction is position-based rather than content-based.Scheduler class uses Python mixins (SchedulerDisaggregationDecodeMixin, SchedulerPPMixin, etc.) that override or extend base methods. This allows arbitrary combinations (e.g., DP + EP + PP + disaggregation + speculative decoding) without combinatorial code paths, but creates implicit dependencies through shared self state. The order of mixin inheritance determines method resolution, which is a subtle correctness concern.pip install && vllm serveserver_args.py configuration surface is a liability for your teamserver_args.py monolith should be split into domain-specific config dataclasses (model config, parallelism config, cache config, serving config) with validation, documentation generation, and deprecation tracking. This is the single highest-impact maintainability improvement.self without explicit interface definitions. Adding typed protocols or abstract methods that each mixin must implement would catch cross-mixin state dependency bugs at import time rather than at runtime under specific parallelism combinations.server_args.py parameter interactions — with hundreds of CLI flags, non-obvious interactions exist (e.g., chunked_prefill_size interacts with max_running_requests and mem_fraction_static). No automated validation of parameter combinations.lang/ frontend is less actively developed than srt/. Complex DSL programs may lag behind runtime capabilities.