TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

KV Cache in Serving Engines: PagedAttention, Continuous Batching, and Prefix Caching

Status: Draft (2026-10-13), partially measured. The papers and official documentation were directly opened and verified on 2026-10-13. Measurements re-cite the values measured with a single 8GB-class GPU, Qwen3-1.7B, and vLLM 0.31.0 from Part 14 of "Toss ML/AI Infra Preparation" on the same site. Values for larger models and multiple GPUs are unmeasured. Writing rules: Measured data is the default, unmeasured items are marked as "Unmeasured", and unverified items are marked as "Unverified".

Table of Contents

1. Throughput is Ultimately a Matter of Batch Size

Re-stating the conclusion of Part 1. Every time decoding generates a single token, it must read the entire set of weights from memory, so running only a single request leaves most of the GPU's calculators idle. If multiple requests are decoded together when reading the weights once, multiple tokens can be created with the same read. Therefore, increasing the batch size increases throughput.

Each request in a batch must keep its own KV in GPU memory. Since the KV is shared using the memory left over after loading the weights, how densely the KV is packed into the same memory determines the batch size, and thus the throughput. Most KV management techniques in serving engines are designed for this single sentence.

Technique What is Saved Path to Throughput
PagedAttention KV memory wasted due to reservation and fragmentation More requests in the same memory → Larger batch
Continuous Batching Empty slots from early-finished requests Filling the batch completely at every step
Chunked Prefill Time that long prefills pause decoding Increasing the batch while respecting token interval constraints
Prefix Caching KV computation and memory for the same prefix Skipping prefill computation and sharing blocks

2. PagedAttention: Dividing KV into Blocks

KV 메모리를 나누는 두 방법 옛 방식 — 요청마다 최대 길이만큼 이어 붙여 예약 A B A 예약 B 예약 틈 틈 아직 안 쓴 예약과 사이의 틈은 다른 요청이 못 쓴다. vLLM 논문: 기존 시스템은 KV 메모리의 20.4~38.2% 만 실제 토큰에 썼다. PagedAttention — 16토큰 블록과 블록 표 요청 A 요청 B A0A1B0 A2 B1 블록 표 A → 3, 7, 1 B → 3, 5 GPU 메모리 0 1 2 3 공유 4 5 6 7 8 9 10 11 · 블록은 빈 곳 어디에나 놓인다 → 틈이 생기지 않는다. · 낭비는 요청마다 마지막 블록의 빈칸뿐이다. · A0 과 B0 은 같은 프롬프트라 3번 블록 하나를 함께 본다. 블록 열쇠 = (앞 블록 해시, 이 블록의 토큰, LoRA 등 추가 정보) 토큰이 찬 칸 예약만 한 칸 빈 블록
Figure: Comparison of Contiguous Reservation and Block Division

Waste in Old Methods

Serving systems prior to vLLM allocated KV space as a single chunk for each request up to the maximum output length in advance. Since it is unknown how many tokens the output will be, it is inevitably allocated generously. The vLLM paper (Kwon et al., SOSP 2023) divides the waste arising here into three categories.

In the paper's measurements, existing systems used only 20.4~38.2% of KV memory for actual token storage. According to a figure in the same paper, when serving a 13B model on an A100, about 65% of the memory is weights and nearly 30% is KV. The KV share is originally small, and more than two-thirds of it is wasted.

Blocks and Block Tables

PagedAttention solves this like virtual memory in operating systems. It divides KV into fixed-size blocks(default 16 tokens) and maintains a block tableof "logical block → physical block" for each request. Blocks are placed anywhere in free GPU memory, and when tokens completely fill one block, a new block is allocated at that time.

The attention kernel follows the block table to read K and V from scattered blocks. Computation remains the same even if they are not a contiguous array.

Sharing Blocks

Managing in block units allows multiple requests to point to the same block. In parallel sampling or beam search, where multiple answers are generated from a single prompt, the KV for the prompt portion is identical, so reference counts are kept on the blocks and they are shared. They are copied only when someone needs to append to that block (copy-on-write). The KV memory saved by this in the paper's measurements is as follows.

Dataset Parallel Sampling Beam Search
Alpaca 6.1~9.8% 37.6~55.2%
ShareGPT 16.2~30.5% 44.3~66.3%

Results

The paper reports that throughput at the same latency level is 2–4x higher than FasterTransformer and Orca (OPT-13B/66B/175B and LLaMA-13B, 1 to 8 A100 40GB/80GB GPUs). Under the ShareGPT workload, the request rate handled was up to 22x higher than FasterTransformer. Since the multiplier varies greatly depending on the comparison target and workload, "2–4x" can be read as a representative value.

3. Continuous Batching: Filling Empty Slots at Every Step

GPU 한 걸음마다 배치에 무엇이 들었나 가로 = 시간, 줄 = 배치의 자리, 칸 하나 = 한 걸음 (가) 정적 배치 — 모두 끝나야 다음 배치 자리 1자리 2자리 3 빈 자리, 새 요청 대기 (나) 연속 배칭 — 빈 자리에 바로 새 요청 자리 1자리 2자리 3 긴 걸음 자리 1·3 의 토큰이 늦다 (다) 청크 프리필 — 긴 프리필을 잘라 디코드와 섞기 자리 1자리 2자리 3 고르게 나온다 프리필 디코드 토큰 하나 빈 자리 긴 칸일수록 그 걸음이 오래 걸린다. 모양은 설명용이고 길이는 실측이 아니다.
Figure: Comparison of Static Batching, Continuous Batching, and Chunked Prefill

Even if memory is saved, slots are wasted if the batching method is poor. This is because output lengths vary by request. Static batchinggroups a few requests to start and does not accept new requests until all of them finish . Even if a 10-token answer finishes early, its slot remains idle until the 500-token answer finishes.

Orca (Yu et al., OSDI 2022) changed scheduling to the unit of a model iteration. At the end of each step, finished requests are returned immediately, and waiting requests are included starting from the next step. This is continuous batching, which most engines use today. The paper reports that for a GPT-3 175B-class model (16 A100 40GB GPUs), when the median per-token latency was set to 190ms, FasterTransformer processed 0.185 requests per second and Orca processed 6.81 requests (36.9x). The baseline for this comparison is static batching, and this difference includes not only continuous batching but also Orca's other designs.

Continuous batching and PagedAttention need each other. For requests to enter and leave at every step, KV space must be allocated and freed on the fly, but chunk-based reservation only increases gaps. Block-level allocation made this possible.

New Problem: Long Prefills Pause Decoding

Continuous batching leaves the problem shown in Figure (b). When a new request comes in, its prefill must be done in a single step, and if the prompt is long, that step takes a long time, during which other requests in the batch cannot receive their next tokens. The Sarathi-Serve paper (Agrawal et al., OSDI 2024) calls this generation stall and reports that under Yi-34B and 2 A100 GPU conditions, such pauses can last up to several seconds.

The solution, as shown in Figure (c), is to cut long prefills into chunks, distribute them across multiple steps, and interleave them with decoding tokens at every step(chunked prefill). In Table 4 of the same paper (Yi-34B, 2 A100 GPUs, single-step token budget 1,024), the P99 token interval was 0.68 seconds with interleaving alone, and 0.14 seconds when using chunks and "fill decode first" together. Under tail latency constraints, the workload handled was 2.6x higher for Mistral-7B (1 A100 GPU) and up to 3.7x higher for Yi-34B (2 A100 GPUs) compared to vLLM (paper abstract).

Our Measurements. While a single request decoding 3,000 tokens on an 8GB-class GPU with Qwen3-1.7B was running, 3 inputs of 3,500 tokens each were inserted, and the token intervals in the inserted section were measured while changing the number of input tokens put into a single step (--max-num-batched-tokens).

Single-Step Input Token Limit Maximum Token Interval in Inserted Section First Token of Long Input Itself
512 69ms 481~494ms
1,024 129ms 468~493ms
2,048 (Default for this version) 227ms (227, 226, 226 over 3 runs) 466~480ms
8,192 (Effective 3,500) 445ms 461~474ms

Chunked prefill reduces intervals but cannot eliminate them. As long as prefill and decoding share the same GPU, they interfere with each other. Disaggregated serving in Part 4 solves this problem in a different way.

4. Prefix Caching: Computing the Same Prefix Only Once

There are many identical prefixes across requests as well. This is true for system prompts attached to all conversations, RAG where multiple queries refer to the same document, and multi-turn conversations that resend the previous turn as-is. As seen in Part 1, if the prefix is the same, its KV is also the same. Therefore, finding blocks already in the GPU and reusing them skips that much prefill.

vLLM's automatic prefix caching (design doc, viewed 2026-10-13) creates a key for each block.

Our Measurements. We attached a different 32-token tail per request to a common prefix of 3,000 tokens and sent them one by one.

Configuration First Request First Token Subsequent Requests First Token (Median)
Prefix Caching ON (Default) 394ms 28ms
OFF 395ms 393ms

When hit, it skipped the 3,000-token prefill, making the first token 14x faster. Conversely, under a load with completely non-overlapping prefixes (2,048 input, concurrency 32), the cost of turning it on was about 1.2% in throughput and about 8% in median time-to-first-token (estimated to be hash calculation overhead, not broken down).

Pitfalls in measurement. If you measure performance by repeating the same sentence, the prefix cache will hit, yielding speeds that a GPU cannot normally achieve. Performance test inputs must vary per request, and a common prefix should be intentionally created only when you want to observe cache effects.

5. When KV Space Falls Short

The fact that the upper limit of the batch size is determined by KV is also evident in numbers. In the same actual measurement environment, the KV space was 22,048 tokens, and for a request of 512 input + 128 output = 640 tokens, about 34 requests can fit.

Concurrent Requests Throughput Median First Token
1 66 tokens/sec 73ms
8 383 tokens/sec 351ms
32 831 tokens/sec 666ms
64 787 tokens/sec 5.7s

When increasing concurrency from 32 to 64, throughput actually decreased and the first token became 8.6x slower. Requests that lack space wait in the queue. If there is even less space, requests already running evict their KV and get kicked out (preemption), then have their prefill recomputed from scratch. At an input of 2,048 and concurrency of 32, preemption occurred 7 times, and at 1,500 input, 256 output, and concurrency of 64, it occurred 22 times, with median time-to-first-token being 12.5s and 35.4s, respectively. Because the same KV is computed twice, throughput does not increase and only latency increases.

The KV capacity varied between 22,048 and 27,504 tokens depending on each server boot, and near the limit like at concurrency 64, that 20% difference changed the first token time by 2.7x. In operations, it is recommended to record GPU KV cache size in server logs and tune the concurrency upper limit to around "the number of requests the KV can hold given the average request length".

6. Conclusion: And the Wall of GPU Memory

Technique Basis Verified Effect
PagedAttention Paper Reduced waste to within a single block, 2-4x throughput at the same latency
Continuous Batching Paper (Orca) 36.9x at the same latency compared to static batching (175B scale, including other designs)
Chunked Prefill Paper (Sarathi-Serve) & Actual Measurement P99 inter-token latency 0.68->0.14s (paper), max interval 445->69ms (actual measurement)
Prefix Cache Actual Measurement First token for 3,000-token prefix 394->28ms

All of these techniques operate inside GPU memory . If GPU space runs short, the prefix cache deletes the oldest blocks first, and recalculates from scratch if the deleted prefix appears again. If there are multiple engine instances, each caches separately, meaning a neighboring instance cannot reuse a KV it has already computed. Part 3 covers LMCache, which places KV outside the GPU (CPU memory, disk, or other servers).

A word from Titi. If you rent out a ping-pong table to "one team for the whole day," many tables sit empty. If you break it down into 30-minute slots, assign the next team right as a slot ends, and let members of the same club share a table, far more people can play in the same gym. PagedAttention and continuous batching do that job.

References

Sign in to like

Comments

No comments yet.

Sign in to leave a comment