Stream Benchmarks
Planned bandwidth and performance measurements for RoExpress Stream. This page will be updated with real in-engine numbers once the benchmark suite is complete.
What will be measured
The benchmark suite will cover five areas:
| Area | What it captures |
|---|---|
| Full packet bandwidth | Raw bytes per second at N players × T tick rate for a fixed schema |
| Delta compression savings | Byte reduction when only 1 of 5 fields changes vs all 5 changing |
| SendExcept vs BroadcastDelta at scale | Server CPU cost of per-player relay vs shared broadcast |
| Fixed vs variable schema | Pack/unpack time and byte count with and without string fields |
| Rate limiter overhead | TokenBucket cost per dropped packet under flood conditions |
Wire size estimates
Based on the wire format ([channelId: u16][seq: u16][payload]), estimated packet sizes for the standard player-movement schema:
Schema: userId (f64) + cf (CFrameLight) + health (u8)
| Field | Type | Wire bytes |
|---|---|---|
| Channel ID + seq | header | 4 B |
| userId | f64 | 8 B |
| cf | CFrameLight | 16 B |
| health | u8 | 1 B |
| Total (full packet) | 29 B |
Estimated bandwidth at scale (full packets, no delta)
| Players | Tick rate | Packets/s (server recv) | Bytes/s (server recv) |
|---|---|---|---|
| 10 | 20 Hz | 200 | ~5.7 KB/s |
| 20 | 20 Hz | 400 | ~11.4 KB/s |
| 50 | 20 Hz | 1,000 | ~28.5 KB/s |
| 100 | 20 Hz | 2,000 | ~57 KB/s |
| 100 | 30 Hz | 3,000 | ~85 KB/s |
Delta compression estimate (CFrameLight moving player)
When a player is moving, typically only cf changes each tick (userId and health are constant). The delta payload contains a 1-byte bitmask plus the changed fields only:
| Scenario | Payload bytes | vs full packet |
|---|---|---|
| All 3 fields changed | 1 (mask) + 25 = 26 B | No savings (mask overhead) |
| cf only changed (moving player) | 1 (mask) + 16 = 17 B | ~34% smaller payload |
| health only changed (hit) | 1 (mask) + 1 = 2 B | ~92% smaller payload |
| Nothing changed (standing still) | 1 (mask) = 1 B | ~96% smaller payload |
Delta compression is most effective for fields that change rarely — health, animation state, flags. For a position field that changes every frame, the savings are modest (mask overhead applies).
Schema design guidance
Until measured benchmarks are available, these rules of thumb apply:
| Rule | Reason |
|---|---|
Prefer CFrameLight over CFrame for humanoids | 16 B vs 28 B — humanoids only rotate on Y axis |
Use u8 for health (0–255) not f32 | 1 B vs 4 B |
Pack boolean groups into { "flags", ... } | Up to 8 booleans in 1 byte vs 8 bytes |
Avoid string fields in high-frequency channels | Variable size disables delta compression and pre-allocation |
Use Vector3int16 for tile-snapped positions | 6 B vs 12 B for Vector3 |
Test methodology (planned)
Benchmarks will be run inside Roblox Studio using Benchmark (the built-in micro-benchmark module) and a controlled multiplayer test environment with simulated players. Each configuration will run for 30 seconds at stable load and report median, p95, and p99 latency alongside total bytes transferred.
See also
Stream | API reference · Stream: Server Side | send methods and delta · Stream: Client Side | throttling recommendations · Benchmark | the micro-benchmark module used in testing