Выберите продукт

KVM/QEMU: virtio и tuned — практический тюнинг производительности и latency

Пошагово разбираем, как ускорить KVM/QEMU на Linux-хосте: проверить virtio-устройства, включить multiqueue на virtio-net, подобрать offload, снизить disk latency через правильный стек и очереди, применить tuned profile и дойти до CPU pinning/NUMA/IRQ-affinity.
KVM/QEMU: virtio и tuned — практический тюнинг производительности и latency

Зачем тюнить virtio в KVM/QEMU

KVM/QEMU давно перестали быть историей про «запустили VM и забыли». В продакшене производительность часто упирается в детали: очереди virtio, количество vCPU у гостя, модель диска (virtio-blk или virtio-scsi), раскладку прерываний, сетевые offload’ы и то, как хостовое ядро управляет энергосбережением и планировщиком.

Хорошая новость: большинство улучшений делаются без «магии» и почти всегда проверяются метриками. Плохая: один неудачный флажок легко добавляет миллисекунды к хвостам (p99) или режет пропускную способность вдвое.

Дальше разберём типовой стек: Linux-хост с KVM/QEMU, Linux-гость, устройства virtio-net и virtio-blk/virtio-scsi, системный тюнинг через tuned. Я буду говорить «хост» — это ОС с qemu-kvm, «гость» — виртуальная машина.

Где прячется latency: virtqueue, IRQ, offload, I/O и CPU

virtio — семейство паравиртуальных устройств: вместо эмуляции железа (e1000/ide/lsi) гость и хост обмениваются дескрипторами через virtqueue. Это снижает накладные расходы, но создаёт несколько типовых точек, где легко потерять производительность или предсказуемость задержек.

  • Очереди (multiqueue): мало очередей — упираетесь в одно ядро; слишком много — растёт overhead и шанс IRQ-«снега».
  • Прерывания и affinity: плохая раскладка IRQ/vCPU даёт миграции кэшей и очереди в softirq.
  • Сетевые offload’ы (GSO/TSO/GRO/CSUM): экономят CPU на throughput, но могут ухудшать tail latency на мелких RPC.
  • Дисковый стек: модель устройства, iothread, режимы кэша, I/O-планировщик на хосте/госте.
  • Энергосбережение: governor, C-states, jitter от частот и пробуждений.

Практика почти всегда одна: сначала фиксируем baseline, затем включаем правильные устройства/очереди, после — приводим в порядок CPU/IRQ и только потом идём в pinning/NUMA.

Проверка multiqueue и распределения прерываний virtio-net в Linux

Минимальные проверки: что у вас сейчас и где узкое место

Перед любым тюнингом зафиксируйте исходные показатели: disk latency/IOPS, сетевой throughput, а также загрузку CPU и перекосы по softirq. Без этого вы не поймёте, стало ли лучше.

Понять, какие устройства у гостя

Внутри гостя:

lsblk -o NAME,TYPE,SIZE,MODEL
lspci -nn | grep -i virtio
ethtool -i eth0

Для сети вы хотите видеть драйвер virtio_net. Для дисков — virtio-модель (обычно vda для virtio-blk или SCSI-слой при virtio-scsi).

Быстрые метрики по хосту

uptime
vmstat 1 10
mpstat -P ALL 1 5
pidstat -t -p $(pidof qemu-system-x86_64) 1 5

Если видите swap (рост si/so), высокий iowait или один CPU забит softirq — тюнинг будет разным: где-то нужно больше очередей, где-то — меньше агрегации или жёстче раскладывать IRQ.

Замер дисковой latency/IOPS (fio)

Внутри гостя (на проде аккуратно: лучше на тестовом файле/томе):

fio --name=randread --filename=/var/tmp/fio.test --size=2G --direct=1 --ioengine=libaio --iodepth=32 --rw=randread --bs=4k --numjobs=4 --time_based --runtime=60 --group_reporting

Смотрите не только среднюю задержку, но и хвосты (p95/p99). Для баз данных и очередей это зачастую важнее максимальных IOPS.

Замер сети (идея)

Для throughput по сети обычно используют iperf3 между двумя VM/хостами в одном сегменте. Для задержек — отдельно измеряйте ping и «прикладную» latency (например, ответ вашего API), потому что хорошая полоса не гарантирует хороший p99.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

virtio-net: multiqueue, offload и IRQ — где чаще всего теряется скорость

virtio-net почти всегда правильный выбор. Но «по умолчанию» вы можете не получить многопоточность: один RX/TX queue упрётся в одно ядро и станет лимитом по PPS/throughput.

Проверяем и включаем multiqueue (гость)

Смотрим, сколько каналов доступно:

ethtool -l eth0

Если сейчас один канал, пробуем увеличить (если драйвер/устройство поддерживает):

ethtool -L eth0 combined 4

Практическое правило: начните с combined = min(vCPU, 4..8). Для маленьких VM (2–4 vCPU) обычно 2–4 очереди дают максимум эффекта без лишнего overhead.

RPS/RFS и softirq: когда multiqueue нет или его мало

Если по архитектуре очередей мало, иногда помогает распределить обработку пакетов через RPS/RFS. Это не замена multiqueue, но может выровнять нагрузку.

Типовой признак проблемы: один CPU забит ksoftirqd, остальные простаивают. Для диагностики:

cat /proc/interrupts | head
cat /proc/net/softnet_stat | head

Если видите явный перекос, дальше логично либо включать multiqueue на устройстве, либо настраивать affinity IRQ и/или RPS (в зависимости от вашей схемы сети и версии ядра).

Offload’ы virtio-net: throughput vs tail latency

Offload’ы обычно включены и экономят CPU на больших потоках. Но для низких задержек (мелкие RPC, очереди, чаты, real-time обработка) иногда полезно отключить часть агрегации и проверить хвосты.

Текущие флаги:

ethtool -k eth0

Кандидаты для A/B-теста:

ethtool -K eth0 gro off gso off tso off

Это не универсальная рекомендация. Отключая GRO/GSO/TSO, вы часто снижаете throughput и повышаете CPU. Делайте сравнение на одинаковой нагрузке и обязательно фиксируйте p95/p99.

virtio-blk vs virtio-scsi: что выбрать и как снизить disk latency

Если нужен «простой и быстрый» диск — virtio-blk часто отлично подходит. Если нужна гибкость (hotplug, сложные конфигурации, больше возможностей на уровне SCSI) — выбирают virtio-scsi. На практике разница часто меньше, чем влияние CPU/IRQ/NUMA и режима работы хранилища на хосте.

Проверьте планировщик I/O в госте

В госте:

lsmod | grep -E 'virtio|scsi'
cat /sys/block/vda/queue/scheduler 2>/dev/null
cat /sys/block/sda/queue/scheduler 2>/dev/null

На современных ядрах для виртуальных дисков обычно разумны none или mq-deadline (зависит от версии ядра и типа backend-хранилища). Если видите «странные» или очень старые значения, иногда дешевле обновить ядро/дистрибутив, чем бесконечно подкручивать параметры вокруг устаревшего стека.

Не путайте «быстро» и «много»: iodepth/numjobs и хвосты

Синтетика с большим iodepth легко рисует красивые IOPS, но p99 latency при этом может стать неприемлемым. Это не «обман», а реальная характеристика очередей и конкуренции за ресурсы.

Для сравнения делайте минимум два профиля тестов:

  • latency-oriented: iodepth=1..4, небольшие блоки, умеренное число потоков;
  • throughput-oriented: iodepth=16..64, больше параллелизма.

Кэширование QEMU и writeback: осторожно

Режимы кэша диска задаются на хосте (libvirt XML или параметры QEMU). Неправильный режим может ускорить «цифры» в бенчмарке, но ухудшить надёжность и поведение при авариях.

Если вы не уверены, какой режим кэша безопасен именно для вашей схемы хранения, держитесь консервативных настроек и сначала обеспечьте корректную модель записи (fsync/барьеры/гарантии backend), а уже потом оптимизируйте производительность.

Во многих реальных случаях больший эффект дают не кэш-флаги, а: правильное распределение CPU/IRQ, настройка очередей и адекватный системный профиль на хосте.

Вывод fio с percentiles задержек (p95/p99) для оценки disk latency в VM

tuned: как выбрать профиль под производительность и latency

tuned — менеджер профилей производительности в Linux. Он меняет governor CPU, параметры энергосбережения, sysctl и ряд опций, влияющих на задержки и throughput. Практическая ценность tuned в том, что вы можете быстро переключиться между профилями и сравнить результат измерениями.

Установка и базовые команды

tuned-adm --version
tuned-adm list
tuned-adm active

Типовая логика выбора профиля:

  • Если важнее максимальная пропускная способность и «ровная» загрузка — часто подходит throughput-performance.
  • Если VM latency-sensitive (БД, очереди, API) — попробуйте latency-performance.
  • На выделенных хостах под виртуализацию в некоторых дистрибутивах встречается профиль уровня virtual-host (название зависит от поставщика).

Применение:

tuned-adm profile latency-performance
tuned-adm active

После переключения обязательно повторите ваши тесты. «На глаз» в теме latency почти всегда ошибочно.

Что в tuned обычно влияет сильнее всего

  • CPU governor: перевод в performance и отказ от агрессивного power saving.
  • Параметры энергосбережения: влияние C-states на wakeup latency.
  • Сетевые sysctl: backlog/буферы и связанные параметры, влияющие на поведение под нагрузкой.

Если хвосты стали лучше, но выросло потребление энергии и средняя загрузка CPU — это типичный компромисс «latency vs efficiency».

Если упираетесь в лимиты CPU/памяти на сервисах внутри VM, проверьте ещё и ограничения systemd: иногда «медленный QEMU» на деле оказывается лимитом cgroups для процесса сервиса. См. материал про лимиты CPU/памяти в systemd.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

CPU pinning, NUMA и раскладка IRQ: когда нужны «взрослые» меры

Если вы уже включили virtio, настроили очереди и подобрали tuned, а latency всё ещё «плавает», часто виноваты миграции vCPU по ядрам, конкуренция с другими задачами на хосте и NUMA-эффекты.

Проверяем NUMA на хосте

lscpu | grep -E 'NUMA|Socket|CPU\(s\)'
numactl --hardware

Если хост NUMA, старайтесь держать vCPU и память VM в пределах одного NUMA-узла (особенно для баз данных). Иначе получите непредсказуемые хвосты из-за удалённой памяти.

Идея pinning: меньше миграций — стабильнее p99

Pinning (закрепление vCPU за физическими CPU) и изоляция ядер под VM уменьшают jitter. Это особенно заметно на высоких PPS/IOPS и при «шумных соседях» на хосте.

Реализация зависит от стека управления (libvirt или чистый QEMU), но цель одна: vCPU, IRQ virtio и (если используете) iothread’ы должны быть распределены осмысленно, а не оставлены на усмотрение планировщика.

Прерывания virtio: почему важен affinity

Даже если у VM 8 vCPU, но все IRQ virtio-net обрабатываются на одном ядре, вы снова получите узкое место. Смотрите /proc/interrupts и настраивайте affinity вручную или через связку irqbalance/tuned (в зависимости от политики на хосте).

Практический сценарий тюнинга: от простого к сложному

  1. Фиксируем baseline: fio (диск), сетевые тесты (throughput и latency), CPU/softirq на хосте.

  2. Проверяем устройства: сеть — virtio-net, диски — virtio-blk или virtio-scsi (не e1000/ide).

  3. Включаем multiqueue для virtio-net и проверяем, что нагрузка распределилась по ядрам.

  4. Тестируем offload’ы: сначала дефолт, затем точечно отключаем GRO/GSO/TSO, если цель — минимальные хвосты.

  5. Переключаем tuned на хосте: сравниваем throughput-performance и latency-performance под вашей нагрузкой.

  6. Если хвосты всё ещё плохие: pinning/NUMA/IRQ-affinity, устранение миграций и конкуренции.

Типовые симптомы и быстрые подсказки

Throughput низкий, CPU свободен

Проверьте multiqueue у virtio-net, не упираетесь ли в single queue, и как распределены IRQ. Часто решение — добавить очереди и правильно разложить прерывания.

Throughput высокий, но p99 latency плохой

Ищите агрегацию пакетов (GRO/GSO), энергосбережение CPU, миграции vCPU, NUMA-эффекты. Уменьшайте «очереди ради очередей»: слишком большой iodepth и слишком много очередей тоже добавляют хвосты.

Всплески задержек «ни с того ни с сего»

Проверьте фоновые задачи на хосте: backup/trim, kswapd и давление памяти, периодические джобы. Иногда проблема не в virtio, а в общей конкуренции за ресурсы — и тогда полезно вернуться к основам выбора конфигурации VDS/хоста (CPU/RAM/диск) и «не экономить на базовом». См. как подобрать план VDS по CPU и RAM.

Контрольный список «хорошей практики»

  • virtio везде: сеть — virtio-net, диски — virtio-blk или virtio-scsi по задаче.

  • Очереди соразмерны CPU: multiqueue не должен быть «максимальным просто потому что можно».

  • tuned включён осмысленно: выбирайте профиль под задачу и подтверждайте тестами.

  • Метрики важнее ощущений: p95/p99 latency, softirq, iowait, распределение IRQ.

  • Стабильность важнее пиков: для БД и API лучше чуть меньше IOPS, но предсказуемая задержка.

Заключение

Тюнинг KVM/QEMU — это управление очередями, прерываниями и политиками CPU/энергосбережения. Начните с очевидного: virtio-net и virtio-blk/virtio-scsi, затем включите multiqueue и подберите профиль tuned. Если tail latency всё ещё страдает — переходите к pinning/NUMA/IRQ-affinity и повторяйте тесты до стабильного результата.

Если вы выбираете площадку под виртуализацию, где важны предсказуемые хвосты и контроль ресурсов, чаще всего удобнее стартовать с изолированного VDS, а не с «общей кухни». Так проще закреплять CPU, понимать I/O и стабилизировать latency под вашей нагрузкой.

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...