Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Бенчмарки
Во что ruststream-sqlx обходится на каждом сообщении: пропускная способность против сырого цикла
sqlx, outbox как плагин, инструкции и выделения памяти его кода.
Против сырого цикла sqlx
Первый график прогоняет каждый сценарий тремя способами на PostgreSQL из стенда. «Сырой цикл
sqlx» - написанный вручную цикл, который выполняет те же операторы, что брокер выполняет для той
же таблицы, в том же порядке, на пуле, построенном так же; он берёт их у диалекта, поэтому два
цикла не могут разойтись. «Крейт вручную» работает с подпиской или издателем этого крейта
собственным циклом, без рантайма. «Сервис RustStream» - сервис, который пишет пользователь:
таблица с #[derive(Inbox)], обработчик #[subscriber] и приложение. Первая разность
показывает, во что этот крейт обходится поверх операторов, которые он выполняет, а вторая - что
сверху добавляет рантайм.
Каждый цикл изображён полосой от лучшего круга до самого медленного: точка отмечает лучший круг, засечка - медиану. Ноль оси - лучший круг сырого цикла, и точка правее нуля значит, что цикл медленнее. Пустая точка отмечает цикл, у которого разница с сырым циклом меньше разброса кругов. Таблица под графиком печатает лучший круг, а в скобках медиану.
Каждое сообщение стоит как минимум захвата, завершения и фиксации, и каждое из них - обмен с базой данных. Строка с отметкой «упирается в базу данных» - та, где сырой цикл хотя бы половину времени каждого сообщения ждал этих обменов. Крейт и рантайм тогда выполняют свою работу внутри ожидания, которое оплачивает и сырой цикл, и строка даёт нижнюю границу их стоимости, а не её измерение.
Outbox как плагин
Outbox работает поверх любого брокера, поэтому измеряется как стоимость для обычного приложения:
одно приложение в трёх вариантах, поверх Redis Pub/Sub из стенда через ruststream-fred и
PostgreSQL из стенда. «Без outbox» - приложение, которое пользователь пишет без него. «Outbox,
написанный вручную» - то же приложение, где запись вставляется перед каждой публикацией, а в
обработчике получается и отмечается, на голом sqlx. «Outbox крейта» - то же приложение с реестром
этого крейта, двумя его слоями и повторной публикацией. Относительно варианта без outbox график
показывает, во что вообще обходится отслеживание сообщения, а относительно ручного outbox - что
механизм крейта добавляет к операторам, которые пользователь выполнял бы в любом случае.
Стоимость кода
График стоимости считает, во что одно сообщение обходится на потоке сервиса: инструкции под
callgrind и выделения памяти под DHAT, в установившемся режиме, против PostgreSQL из стенда. В
счёт входят рантайм, этот крейт и кодирование и декодирование в драйвере sqlx на этом потоке;
сервер базы данных - другой процесс, и в счёт он не входит. «Холодный старт» - разовая стоимость
запуска сервиса: открытие соединений пула, проверки брокера при старте и первая доставка. Счёт
outbox запускает те же приложения поверх MemoryBroker, поэтому транспорта в его числе нет.
Результаты
- Сырой цикл sqlx
- Крейт вручную
- Сервис RustStream
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
ruststream-sqlx 0.7.0 on ruststream 0.7.1, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.11-x64v3-xanmod1-1, postgres:17-alpine, mysql:8.0, redis:7-alpine in Docker on the host network, without durability; SQLite bundled with sqlx, on a local file in WAL mode; the outbox over MemoryBroker in the code table and over Redis Pub/Sub in the wall clock, измерено 2026-10-18. Как сняты числа
- неразличимо
- +2.1% (упирается в базу данных)
- неразличимо
- неразличимо (упирается в базу данных)
- неразличимо
- неразличимо (упирается в базу данных)
- -3%
- -2.5%
- неразличимо
- неразличимо
- неразличимо
- неразличимо (упирается в базу данных)
- неразличимо
- неразличимо (упирается в базу данных)
- неразличимо
- неразличимо (упирается в базу данных)
- неразличимо
- неразличимо (упирается в базу данных)
Показать числа таблицей
| Сценарий | Сырой цикл sqlx | Крейт вручную | Сервис RustStream | Оверхед |
|---|---|---|---|---|
| row lock claim, JSON decode into a small struct, delete each | 6 149 msg/s (6 103) | 6 136 msg/s (5 986) (неразличимо к сырому циклу) | 6 018 msg/s (5 996) | +2.1% (упирается в базу данных) |
| row lock claim, reply inserted through this crate's default publisher, delete each | 5 150 msg/s (4 984) | 5 103 msg/s (5 092) (неразличимо к сырому циклу) | 5 007 msg/s (4 937) | неразличимо (упирается в базу данных) |
| row lock claim in batches of 64, delete each | 29 198 msg/s (29 006) | 29 043 msg/s (28 629) (неразличимо к сырому циклу) | 28 724 msg/s (28 676) | неразличимо (упирается в базу данных) |
| lease claim, JSON decode into a small struct, delete each | 3 125 msg/s (3 098) | 3 219 msg/s (3 193) (-3% к сырому циклу) | 3 202 msg/s (3 177) | -2.5% |
| advisory lock claim, JSON decode into a small struct, delete each | 4 611 msg/s (4 572) | 4 558 msg/s (4 462) (неразличимо к сырому циклу) | 4 565 msg/s (4 295) | неразличимо |
| by-name subscription, row lock claim, delete each | 6 089 msg/s (5 910) | 6 025 msg/s (5 773) (неразличимо к сырому циклу) | 5 980 msg/s (5 784) | неразличимо (упирается в базу данных) |
| row mode, the row decoded by the driver, delete each | 5 805 msg/s (5 771) | 5 769 msg/s (5 662) (неразличимо к сырому циклу) | 5 759 msg/s (5 742) | неразличимо (упирается в базу данных) |
| repository publish, one insert each | 26 723 msg/s (26 721) | 27 814 msg/s (27 485) (неразличимо к сырому циклу) | 27 640 msg/s (26 771) | неразличимо (упирается в базу данных) |
| routed publish, one insert each | 29 182 msg/s (27 701) | 27 947 msg/s (26 567) (неразличимо к сырому циклу) | 27 295 msg/s (26 896) | неразличимо (упирается в базу данных) |
- Без outbox
- Outbox, написанный вручную
- Outbox крейта
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
- неразличимо
- +76.2%
- +75.9% (неразличимо к ручному)
- +86.3%
- +86.5% (неразличимо к ручному)
- +84.9%
- +85.2% (неразличимо к ручному)
Показать числа таблицей
| Сценарий | Без outbox | Outbox, написанный вручную | Outbox крейта | Оверхед | К outbox, написанному вручную |
|---|---|---|---|---|---|
| outbox plugin, an untracked message through both layers | 53 058 msg/s (52 720) | - | 53 160 msg/s (52 178) | неразличимо | - |
| outbox plugin, a tracked publish from outside a handler | 66 275 msg/s (66 203) | 15 761 msg/s (15 425) (+76.2% к варианту без outbox) | 15 961 msg/s (15 395) | +75.9% | неразличимо |
| outbox plugin, a tracked delivery fetched and marked | 64 200 msg/s (61 442) | 8 821 msg/s (8 600) (+86.3% к варианту без outbox) | 8 682 msg/s (8 635) | +86.5% | неразличимо |
| outbox plugin, a tracked round trip: recorded, delivered, fetched and marked | 54 357 msg/s (53 776) | 8 191 msg/s (8 143) (+84.9% к варианту без outbox) | 8 044 msg/s (8 025) | +85.2% | неразличимо |
AMD Ryzen 9 7900X 12-Core Processor, x86_64, 427-5912 MHz, 12 physical, 24 logical, 62.4 GiB, unknown, Linux 7.2.11-x64v3-xanmod1-1, 1.99.0, 3.25.1, bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only), ruststream-sqlx inbox,outbox,postgres,mysql,sqlite,chrono; ruststream macros,json,memory; ruststream-fred default. ruststream-sqlx 0.7.0, ruststream 0.7.1, измерено 2026-10-18.
Показать числа таблицей
| Сценарий | Инструкции | Выделения | Холодный старт |
|---|---|---|---|
| row lock claim, JSON decode into a small struct, delete each | 44 796,1 | 32 | 334 632 / 355 |
| row lock claim, reply inserted through this crate's default publisher, delete each | 66 613,4 | 44 | 337 677 / 353 |
| row lock claim in batches of 64, delete each | 14 281,5 | 12,6 | 334 178 / 358 |
| lease claim, JSON decode into a small struct, delete each | 51 541,4 | 28 | 397 875 / 393 |
| advisory lock claim, JSON decode into a small struct, delete each | 66 800,8 | 47,1 | 421 572 / 494 |
| by-name subscription, row lock claim, delete each | 47 474,3 | 32 | 356 127 / 359 |
| row mode, the row decoded by the driver, delete each | 43 674,9 | 32 | 338 529 / 364 |
| repository publish, one insert each | 23 890,9 | 15 | 144 459 / 128 |
| routed publish, one insert each | 23 429 | 15 | 145 266 / 129 |
| outbox plugin, an untracked message through both layers | 7 238,2 | 6 | 251 239 / 250 |
| outbox plugin, a tracked publish from outside a handler | 23 232,9 | 15 | 183 040 / 161 |
| outbox plugin, a tracked delivery fetched and marked | 51 016,7 | 30 | 280 164 / 271 |
| outbox plugin, a tracked round trip: recorded, delivered, fetched and marked | 75 639,3 | 42,1 | 328 380 / 311 |
Счёт стоит рядом с циклами, против которых он измерен: для inbox это сырой цикл sqlx, а для outbox - приложение без outbox и приложение с outbox, написанным вручную.
| Сценарий | Сервис, инструкции | Сырой цикл, инструкции | Сервис, выделения | Сырой цикл, выделения |
|---|---|---|---|---|
| row lock claim, JSON decode into a small struct, delete each | 44 796,1 | 40 310,6 | 32 | 33 |
| row lock claim, reply inserted through this crate's default publisher, delete each | 66 613,4 | 60 551,5 | 44 | 45 |
| row lock claim in batches of 64, delete each | 14 281,5 | 12 300,7 | 12,6 | 12,4 |
| lease claim, JSON decode into a small struct, delete each | 51 541,4 | 47 133 | 28 | 28 |
| advisory lock claim, JSON decode into a small struct, delete each | 66 800,8 | 58 844,8 | 47,1 | 47,1 |
| by-name subscription, row lock claim, delete each | 47 474,3 | 40 384,5 | 32 | 33 |
| row mode, the row decoded by the driver, delete each | 43 674,9 | 39 836,3 | 32 | 33 |
| repository publish, one insert each | 23 890,9 | 20 830,8 | 15 | 12 |
| routed publish, one insert each | 23 429 | 20 830,8 | 15 | 12 |
| Сценарий | Инструкции (без outbox / вручную / outbox) | Выделения (без outbox / вручную / outbox) |
|---|---|---|
| outbox plugin, an untracked message through both layers | 6 788,2 / - / 7 238,2 | 6 / - / 6 |
| outbox plugin, a tracked publish from outside a handler | 742,2 / 22 349,9 / 23 232,9 | 2 / 16 / 15 |
| outbox plugin, a tracked delivery fetched and marked | 4 877,7 / 47 021,6 / 51 016,7 | 7 / 30 / 30 |
| outbox plugin, a tracked round trip: recorded, delivered, fetched and marked | 6 821,3 / 68 347,8 / 75 639,3 | 6 / 39 / 42,1 |
Пропускная способность
Заполненную таблицу на каждой базе данных разбирает одна подписка, смонтированная с workers(n),
на пуле из 16 соединений, по одной доставке или пакетами по 64. PostgreSQL и MySQL используют
форму блокировки строк. SQLite использует форму аренды, потому что у неё нет блокировок строк.
Сырой цикл запускает n задач на одном пуле, и каждая захватывает, читает и удаляет, пока её захват
не вернётся пустым. Цикл крейта запускает n подписок на том же пуле, каждую на собственном
брокере. Сервис запускает одну подписку, которая захватывает для всех своих воркеров. Ячейки
outbox монтируют ретранслятор и приёмник с workers(n) в каждом из трёх вариантов outbox.
- Сырой цикл sqlx
- Крейт вручную
- Сервис RustStream
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
ruststream-sqlx 0.7.0 on ruststream 0.7.1, измерено 2026-10-18. Как сняты числа
- неразличимо
- неразличимо
- неразличимо
- +18.5%
- неразличимо
- +19%
- неразличимо
- неразличимо
- неразличимо
- неразличимо
- неразличимо
- +21.6%
Показать числа таблицей
| Сценарий | Сырой цикл sqlx | Крейт вручную | Сервис RustStream | Оверхед |
|---|---|---|---|---|
| по одной, workers(1) | 6 606 msg/s (6 534) | 6 498 msg/s (6 345) (неразличимо к сырому циклу) | 6 519 msg/s (6 489) | неразличимо |
| по одной, workers(4) | 21 422 msg/s (20 667) | 20 365 msg/s (20 352) (неразличимо к сырому циклу) | 17 465 msg/s (16 553) | +18.5% |
| по одной, workers(8) | 35 388 msg/s (35 358) | 35 013 msg/s (34 770) (неразличимо к сырому циклу) | 28 664 msg/s (28 526) | +19% |
| пакетами по 64, workers(1) | 31 095 msg/s (30 671) | 30 127 msg/s (30 047) (неразличимо к сырому циклу) | 29 910 msg/s (29 658) | неразличимо |
| пакетами по 64, workers(4) | 100 358 msg/s (94 995) | 96 291 msg/s (93 160) (неразличимо к сырому циклу) | 94 292 msg/s (93 376) | неразличимо |
| пакетами по 64, workers(8) | 154 114 msg/s (153 177) | 154 622 msg/s (151 889) (неразличимо к сырому циклу) | 120 889 msg/s (119 422) | +21.6% |
- Сырой цикл sqlx
- Крейт вручную
- Сервис RustStream
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
ruststream-sqlx 0.7.0 on ruststream 0.7.1, измерено 2026-10-18. Как сняты числа
- неразличимо
- +16.4%
- неразличимо
- +25.5%
- неразличимо
- +17.8%
- неразличимо
- неразличимо
- неразличимо
- неразличимо
- неразличимо
- неразличимо
Показать числа таблицей
| Сценарий | Сырой цикл sqlx | Крейт вручную | Сервис RustStream | Оверхед |
|---|---|---|---|---|
| по одной, workers(1) | 7 626 msg/s (7 409) | 6 791 msg/s (6 498) (неразличимо к сырому циклу) | 6 376 msg/s (6 329) | +16.4% |
| по одной, workers(4) | 17 830 msg/s (16 166) | 16 316 msg/s (15 688) (неразличимо к сырому циклу) | 13 281 msg/s (13 131) | +25.5% |
| по одной, workers(8) | 21 885 msg/s (21 792) | 19 070 msg/s (15 962) (неразличимо к сырому циклу) | 17 994 msg/s (17 839) | +17.8% |
| пакетами по 64, workers(1) | 36 152 msg/s (35 674) | 35 752 msg/s (34 773) (неразличимо к сырому циклу) | 35 228 msg/s (35 088) | неразличимо |
| пакетами по 64, workers(4) | 107 344 msg/s (107 082) | 102 923 msg/s (86 929) (неразличимо к сырому циклу) | 99 924 msg/s (95 386) | неразличимо |
| пакетами по 64, workers(8) | 158 847 msg/s (132 613) | 147 257 msg/s (139 066) (неразличимо к сырому циклу) | 143 767 msg/s (120 226) | неразличимо |
- Сырой цикл sqlx
- Крейт вручную
- Сервис RustStream
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
ruststream-sqlx 0.7.0 on ruststream 0.7.1, измерено 2026-10-18. Как сняты числа
- +3.3%
- +3.3%
- +4.2%
- +63.9%
- +3%
- +65.5%
- +5%
- неразличимо
- неразличимо
- неразличимо
- неразличимо
- неразличимо
Показать числа таблицей
| Сценарий | Сырой цикл sqlx | Крейт вручную | Сервис RustStream | Оверхед |
|---|---|---|---|---|
| по одной, workers(1) | 14 073 msg/s (13 850) | 13 609 msg/s (13 565) (+3.3% к сырому циклу) | 13 611 msg/s (13 599) | +3.3% |
| по одной, workers(4) | 14 453 msg/s (14 266) | 13 846 msg/s (13 728) (+4.2% к сырому циклу) | 5 218 msg/s (4 723) | +63.9% |
| по одной, workers(8) | 14 244 msg/s (14 181) | 13 814 msg/s (13 733) (+3% к сырому циклу) | 4 916 msg/s (4 754) | +65.5% |
| пакетами по 64, workers(1) | 33 167 msg/s (33 147) | 31 521 msg/s (31 281) (+5% к сырому циклу) | 33 092 msg/s (31 648) | неразличимо |
| пакетами по 64, workers(4) | 34 067 msg/s (33 800) | 35 105 msg/s (33 255) (неразличимо к сырому циклу) | 34 839 msg/s (33 646) | неразличимо |
| пакетами по 64, workers(8) | 35 446 msg/s (34 634) | 34 829 msg/s (33 519) (неразличимо к сырому циклу) | 35 544 msg/s (35 537) | неразличимо |
- Без outbox
- Outbox, написанный вручную
- Outbox крейта
- круги, от лучшего до самого медленного
- лучший круг
- медианный круг
- разброс кругов
- неразличимо
ruststream-sqlx 0.7.0 on ruststream 0.7.1, измерено 2026-10-18. Как сняты числа
- +85.2%
- +85.8% (+3.7% к ручному)
- +50.8%
- +51.9% (неразличимо к ручному)
- +37.2%
- +39.7% (+3.9% к ручному)
Показать числа таблицей
| Сценарий | Без outbox | Outbox, написанный вручную | Outbox крейта | Оверхед | К outbox, написанному вручную |
|---|---|---|---|---|---|
| по одной, workers(1) | 54 941 msg/s (52 927) | 8 128 msg/s (8 097) (+85.2% к варианту без outbox) | 7 826 msg/s (7 663) | +85.8% | +3.7% |
| по одной, workers(4) | 51 743 msg/s (51 332) | 25 440 msg/s (25 275) (+50.8% к варианту без outbox) | 24 866 msg/s (24 810) | +51.9% | неразличимо |
| по одной, workers(8) | 50 650 msg/s (45 681) | 31 813 msg/s (31 242) (+37.2% к варианту без outbox) | 30 560 msg/s (29 582) | +39.7% | +3.9% |
Машина
| Процессор | AMD Ryzen 9 7900X 12-Core Processor |
|---|---|
| Архитектура | x86_64 |
| Частота | 427-5912 MHz |
| Ядра | 12 physical, 24 logical |
| Память | 62.4 GiB |
| Скорость памяти | unknown |
| Операционная система | Linux 7.2.11-x64v3-xanmod1-1 |
| Базы данных | postgres:17-alpine, mysql:8.0, redis:7-alpine in Docker on the host network, without durability; SQLite bundled with sqlx, on a local file in WAL mode; the outbox over MemoryBroker in the code table and over Redis Pub/Sub in the wall clock |
| Круговая задержка | 17.4 us (median of 2000 `SELECT 1` round trips on one Postgres connection) |
| Компилятор | 1.99.0 |
| sqlx | 0.9.0 |
| Профиль сборки | bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only) |
| Фичи | ruststream-sqlx inbox,outbox,postgres,mysql,sqlite,chrono; ruststream macros,json,memory; ruststream-fred default |
| RUSTFLAGS | none (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU) |
| Valgrind | 3.25.1 |
Числа берутся из файла docs/benchmarks/results.json этой версии, который записывают рецепты
бенчмарков, и публикуются рядом со страницами как
benchmarks/results.json.
Как они сняты, объясняет страница Методология, а какие выводы они позволяют
сделать, - страница Числа.