CephXXXVIII · RBD PerformanceRBD Performance
Queue depth: the parameter that decides RBD throughput
What you'll learn
- Explain the relationship between queue depth, latency, and IOPS
- Measure the effective queue depth of a workload
- Configure queue depth at each layer
- Recognise a workload that cannot be helped by tuning
Prerequisites
None — start here.
Verified against Ceph Tentacle 20.2.x · Ceph Squid 19.2.x (supported previous) · cephadm matches the verified Ceph release · podman 4.x · csi-rbd and csi-cephfs current · RBD / CephFS / RGW current (matches Ceph release) · Linux kernel 5.15+ (5.10 minimum) · Ubuntu 24.04 LTS (Ceph host baseline) · Debian 12 (Bookworm) (Ceph host baseline) · Rocky Linux / RHEL / AlmaLinux 9.x (Ceph host baseline) · Proxmox VE 9.x (cross-course integration) · Kubernetes 1.31+ (cross-course integration) · 2026-08-18
Why this matters in production
Ceph’s per-operation latency is what it is: two network round trips plus a device commit. You cannot tune it below that. Throughput, however, scales with how many operations are in flight — so the single most important performance question about an RBD workload is its queue depth, and it is the one least often asked.
The arithmetic
IOPS = queue_depth / latency
| Queue depth | Latency | IOPS |
|---|---|---|
| 1 | 1 ms | 1,000 |
| 8 | 1 ms | 8,000 |
| 32 | 1 ms | 32,000 |
| 128 | 1.2 ms | ~107,000 |
Latency stays roughly flat until the cluster approaches saturation, at which point queueing begins and it rises. Until then, concurrency is free throughput.
The consequence for single-threaded workloads
A single-threaded synchronous writer has queue depth 1, permanently. At 1 ms latency it achieves 1,000 IOPS and no amount of cluster tuning changes that — the cluster is idle between its operations.
# queue depth 1: latency-bound
fio --name=qd1 --ioengine=rbd --pool=rbd-vms --rbdname=test \
--rw=randwrite --bs=4k --iodepth=1 --runtime=60 --time_based
# queue depth 64: concurrency-bound
fio --name=qd64 --ioengine=rbd --pool=rbd-vms --rbdname=test \
--rw=randwrite --bs=4k --iodepth=64 --runtime=60 --time_based
The second will show far higher IOPS at similar per-operation latency. That gap is the entire performance story for most RBD workloads.
Measuring what you have
# in the guest — avgqu-sz is the effective queue depth
iostat -x 5
# at the image level
rbd perf image iostat --pool rbd-vms
An avgqu-sz near 1 means the workload is serialised and Ceph tuning will
not help it. A value in the tens means concurrency is available and
cluster capacity is what matters.
Configuring it
# kernel RBD: the block device queue
cat /sys/block/rbd0/queue/nr_requests
echo 512 > /sys/block/rbd0/queue/nr_requests
# librbd: in-flight operation limits
ceph config set client rbd_concurrent_management_ops 20
# QEMU: use multiple virtio queues
# <driver name='qemu' queues='8'/>
But raising limits does nothing if the application does not generate concurrency. The lever is usually in the application: more threads, async I/O, batching, or removing an unnecessary fsync.
Quiz
Knowledge check · 4 questions
Q1. A single-threaded application with synchronous writes achieves 900 IOPS on RBD. What will cluster tuning achieve?
Q2. Below cluster saturation, increasing queue depth raises throughput without materially raising latency.
Q3. Respond to a performance complaint from an application team.
A team reports that their application achieves only 1,100 IOPS on an RBD volume and asks for the cluster to be tuned. The cluster serves 90,000 IOPS in aggregate and shows no latency outliers or saturation.
Q4. Why does capacity planning target a utilisation ceiling rather than maximum measured throughput?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Measure the workload’s queue depth before investigating the cluster for any RBD performance complaint; it distinguishes the two most common causes in one command and determines who owns the fix. Plan capacity against a utilisation ceiling rather than peak benchmark throughput, and say so when quoting benchmark figures.
Cross-course references
- Kubernetes: application concurrency determines throughput on PVC-backed storage identically
- Linux: Little’s Law applies to every queueing system, and this is a direct application of it