× Install ThecoreGrid App
Tap below and select "Add to Home Screen" for full-screen experience.
B2B Engineering Insights & Architectural Teardowns

io_uring разгружает CPU через асимметричный I/O

Асимметричный io_uring перераспределяет I/O с application cores на выделенные ядра. Это меняет баланс CPU, latency и throughput в высоконагруженных системах.

Современные multi-core системы упираются не только в сеть или диск, но и в конкуренцию за CPU. В Seastar каждый core запускает свой shard с реактором и выполняет как вычисления, так и низкоуровневые I/O операции. В симметричной модели io_uring каждый shard держит свой ring и иногда обходит его через “fast path” с синхронными syscalls. Это экономит время на неблокирующих сокетах, но в итоге смешивает compute и I/O на одних и тех же ядрах. При росте нагрузки это приводит к ухудшению cache locality и к конкуренции между обработкой запросов и системными вызовами.

Идея решения проста: если часть I/O уже обрабатывается выделенными networking cores (через IRQ и SoftIRQ), логично перенести туда больше работы. Асимметричный backend io_uring использует SQ polling и привязку kernel worker threads к этим ядрам. Application shards перестают выполнять синхронные syscalls. Они только ставят запросы в submission queue. Вся цепочка выполнения I/O уходит на networking cores. Это освобождает CPU для вычислений и снижает вмешательство в горячие кэши. Компромисс очевиден: появляется риск перегрузить ограниченное число networking cores и получить новый bottleneck.

Реализация опирается на shared-nothing модель Seastar. Чтобы не вводить блокировки и межшардовую синхронизацию, каждый shard сохраняет собственный io_uring instance. При этом worker pool делится на уровне ядра, чтобы не размножать kernel threads и не перегружать CPU. Шарды группируются, и каждая группа обслуживается выделенным networking core. Важно, что fast path со спекулятивными syscalls полностью убран. Это принципиально: любой обход io_uring разрушает асимметрию и возвращает нагрузку на application cores. Топология тоже влияет: NUMA и SMT учитываются через hwloc, чтобы минимизировать межузловые обращения и снизить latency обмена через ring buffers.

Отдельно рассматривались buffer rings. Они позволяют заранее зарегистрировать буферы и сократить накладные расходы на выделение памяти. Были протестированы варианты с фиксированными буферами, с разбиением крупных операций на цепочки (IOSQE_IO_LINK) и с несколькими ring’ами разного размера. Но интеграция конфликтует с текущей моделью управления памятью в Seastar. Это потребовало бы более глубоких архитектурных изменений, поэтому от идеи отказались на данном этапе.

Результаты показывают, что поведение сильно зависит от профиля нагрузки. В тесте с одним shard асимметричный io_uring даёт около 15% прироста throughput и улучшает p50 latency. Это ожидаемо: освобождённый CPU быстрее обрабатывает пользовательский код. Но при увеличении числа shards картина меняется. Один networking core становится узким местом. Профилирование через perf показывает, что до 40–50% времени уходит на memory copying внутри kernel. Ранее эта нагрузка была распределена между application cores во время syscalls. Теперь она сконцентрирована на одном ядре и упирается в его пропускную способность.

Это важное наблюдение. Асимметричный io_uring выигрывает там, где есть заметная доля вычислений или ожиданий. В чистых I/O сценариях (network-bound throughput) перенос нагрузки может ухудшить масштабирование. Но в реальных системах, таких как базы данных, запросы редко состоят только из передачи байтов. Есть парсинг, бизнес-логика, координация. В таких условиях освобождение application cores даёт более предсказуемую latency и лучший баланс системы.

Итог — это прагматичный компромисс. Асимметричный io_uring не универсально быстрее. Он меняет распределение работы: меньше шума на application cores, больше давления на networking cores. Архитектурно это согласуется с трендом на изоляцию ресурсов и явное управление CPU. Но требует внимательного тюнинга: количества worker cores, их привязки и понимания профиля нагрузки. Без этого легко заменить одну точку деградации на другую.

Ознакомиться с источником

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.