Voxal performance benchmark

linux/x64 · 4 cores (Intel(R) Xeon(R) Processor @ 2.80GHz) · network unshaped-loopback
18 runs · 2026-09-18T14:07:24.193Z · run full-1

Read these numbers with their limits. Every peer of a room runs in one browser on one machine over loopback, so latency is a floor, not a field measurement, and CPU and memory are whole-room totals that must not be divided by the peer count. Nothing here asserts a threshold — the suite only checks that the call was working, so a zero means “this cost nothing”, never “this never connected”. See docs/benchmarking.md.
Extra upload per peer added
43 kb/s
Audio is a full mesh, so a speaker sends one stream to every other peer. A product built on an SFU pays this once, not once per peer.
Join a live room
246 ms
until the first audio, over 3 reps
Host vanishes
7.9 s
until audio is back, 3 survivors
Each peer, on camera
561 kb/s
extra upload per peer added, cameras on
See a live room
586 ms
until every camera is on screen, over 3 reps
Peak room CPU
217%
the whole room on 4 cores

Upload grows with the room

Both lines climb because audio is a full mesh. The listener line climbs too: usedtx=0 keeps packets flowing while muted, so everyone in the room pays for the mesh, not only whoever is talking.

Speaker uploadListener upload
050 kb/s100 kb/s150 kb/s200 kb/s250 kb/s2346Peers in the room220 kb/s239 kb/s
Show the numbers
PeersSpeakersSpeaker upListener upListener downRTTLossRoom CPURoom RSS
2148 kb/s35 kb/s48 kb/s1 ms0.0%30%1085 MiB
3197 kb/s86 kb/s100 kb/s1 ms0.0%60%1314 MiB
41145 kb/s137 kb/s152 kb/s1 ms0.0%107%1553 MiB
61220 kb/s239 kb/s254 kb/s3 ms0.0%217%2078 MiB
66320 kb/s——2 ms0.0%173%2135 MiB

What the room costs the machine

Every peer runs in one browser here, so this is the whole room on one machine — never divide it by the peer count. CPU also carries real run-to-run variance; compare it only across repeats, and only between configurations measured back to back.

050%100%150%200%250%2346Peers in the room217%
Show the numbers
PeersRoom CPURoom RSS
230%1085 MiB
360%1314 MiB
4107%1553 MiB
6217%2078 MiB

What noise suppression costs

rnnoise is the desktop default, so this is a cost the product pays unless someone changes it. Same room size and the same speakers in every row — only the mode changes.

off53%browser60%rnnoisedesktop default73%
Show the numbers
ModePeersSpeaker upRoom CPURoom RSSJS heap
off3102 kb/s53%1375 MiB4 MiB
browser3102 kb/s60%1372 MiB4 MiB
rnnoise (default)3102 kb/s73%1397 MiB4 MiB

Camera: one encode per peer

Under the p2p-only preference this harness pins, camera is a full mesh too — so a sharer encodes and uploads one stream per other peer, at roughly twenty times an Opus stream. The shipped default may route this through an SFU above two participants instead, and that topology is not measured here. This machine ran out of room. One browser was encoding every peer's camera at once, and when that happens the frame rate falls first — while the encoder still blames its own bitrate cap. Read the rows below as a ceiling of the harness, not of the app.

Sharer uploadReceiver download
0500 kb/s1.00 Mb/s1.50 Mb/s2.00 Mb/s234Peers in the room, all on camera1.75 Mb/s1.59 Mb/s
Show the numbers
PeersCamerasSharer upReceiver downPicture sentRoom CPURoom RSS
2all (2)632 kb/s625 kb/s960×540 @ 30 fps (bandwidth)93%1399 MiB
3all (3)1.01 Mb/s1.01 Mb/s853×480 @ 16 fps223%1799 MiB
411.90 Mb/s631 kb/s853×480 @ 30 fps200%1857 MiB
4all (4)1.75 Mb/s1.59 Mb/s853×480 @ 4 fps (bandwidth)337%2270 MiB

What a camera background costs

Segmentation runs locally — MediaPipe in WebAssembly plus a WebGL composite — so it is paid in CPU and frame rate, never on the wire. Still running counts the sharing peers that still had the effect on at the end: the app turns a background off in silence both when the runtime cannot start and when the device cannot sustain it, so a 0 there means the row is not the cost of the effect.

offdefault80%blurthe app gave up here160%
Show the numbers
BackgroundPeersCamerasStill runningSharer upPicture sentRoom CPU
off (default)210/1611 kb/s960×540 @ 30 fps80%
blur210/1627 kb/s1280×720 @ 30 fps160%

Screen share

A screen is not a camera: its ceiling is 1.5 Mb/s rather than 600 kb/s, it is pinned to maintain-resolution so it drops frames rather than letters, and the peer-count downscale never touches it.

Show the numbers
PeersSharer upWatcher downPicture sentRoom CPURoom RSS
3920 kb/s460 kb/s1280×720 @ 20 fps130%1558 MiB

Timings

Joining a call already in progress
Signaling opens in 36 ms, and the first audio arrives at 246 ms. The clock starts at the join, not at browser launch — a real user already has a browser open.
Losing the host
A new host is elected at 7099 ms and audio is back at 7917 ms — the same moment, give or take, and both are simply the ~7 s heartbeat timeout. The room is leaderless for seven seconds; it is never silent, because audio connections to non-host peers are never torn down during a migration.
Joining a room that is already on camera
The room is audible at 322 ms and every camera in it is on screen at 586 ms. Hearing and seeing are separate numbers: a picture needs its own call per sharer, a keyframe and a decoder, and the mesh builds them one at a time.