18-LAB / Documentation
Benchmarks against tosu
vosu 1.1.0 (c791512) against the tosu 4.26.2 baseline, run against live
osu!stable and osu!lazer clients on Windows and Linux. Lower is better on every chart. The
tosu / vosu chip is tosu's value divided by vosu's: above 1× means vosu used less time or memory,
below 1× means tosu did.
These numbers come from the "Released tosu comparison" section of vosu's maintained
benchmark guide
(guide commit a2e3358). Live readers and daemon measurements were rerun on 2026-10-17
with the 1.1.0 release commit; the separately labeled hot paths retain their latest 2026-10-11
vosu v1.0.0 measurements. A rerun replaces its rows; earlier results remain in Git history.
1.1.0: before and after
These charts compare the 1.0.2 code (5b855e1, benchmark prerequisites only, no optimization)
with the 1.1.0 release commit c791512 on Linux and native Windows, measured on 2026-10-17.
Builds ran alternately for three rounds, pinned to vCPU 2, with no client or daemon running.
Bars are medians of three Criterion means; ranges span them. The precise reader is the median
of fifteen invocations. The chip is the speedup since 1.0.2.
Criterion used 2 s warm-up, 20 s measurement and 60 samples. The 1.0.2 filtered harness overrides
these with 1 s warm-up, 2 s measurement and 10 samples; 1.1.0 uses the requested options.
Linux used default release features; Windows used MSVC and --no-default-features.
See the paired method.
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| regular_reader/lazer_gameplay | 92.27 µs (91.63–126.40) | 16.66 µs (16.43–16.68) |
| regular_reader/lazer_menu | 108.19 µs (107.58–123.73) | 29.79 µs (29.42–29.86) |
| regular_reader/stable_gameplay | 45.71 µs (45.27–45.71) | 12.70 µs (12.42–12.73) |
| regular_reader/stable_menu | 49.11 µs (48.74–49.35) | 10.58 µs (10.31–10.63) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| memory_reader_bench (lazer precise capture) | 10.64 µs (10.44–10.97) | 8.789 µs (8.687–8.959) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| filtered_projection/v2_identical/100 | 6.179 ms (6.151–6.434 ms) | 19.90 µs (19.84–19.96 µs) |
| filtered_projection/v2_unique/100 | 6.950 ms (6.796–7.194 ms) | 31.71 µs (31.61–31.72 µs) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| v2_subscription/distinct_plans/1000 | 409.1 µs (409.0–435.8) | 85.58 µs (85.27–86.55) |
| v2_subscription/shared_plan/1000 | 209.2 µs (208.4–209.2) | 61.28 µs (59.84–61.41) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| serializers_cold/v1 | 4.450 µs (4.437–5.939) | 2.647 µs (2.639–2.818) |
| serializers_cold/v2 | 10.54 µs (10.41–10.69) | 3.953 µs (3.907–4.158) |
| serializers_cold/v2_precise | 3.914 µs (3.881–3.990) | 2.718 µs (2.690–2.954) |
| serializers_cold/stream_companion | 6.527 µs (6.501–6.539) | 3.230 µs (3.162–3.250) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| http_v2/cold_connection | 45.38 µs (43.85–46.49) | 48.20 µs (45.24–54.50) |
| http_v2/keep_alive | 5.575 µs (5.540–5.618) | 5.710 µs (5.634–5.735) |
| http_v2/dispatch_only | 364.3 ns (354.9–374.4) | 381.4 ns (380.3–382.1) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| memory_reader_bench (lazer precise capture) | 19.10 µs (18.97–24.02) | 19.14 µs (18.97–19.46) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| filtered_projection/v2_identical/100 | 7.679 ms (7.656–7.713 ms) | 25.32 µs (24.96–25.42 µs) |
| filtered_projection/v2_unique/100 | 7.688 ms (7.646–7.900 ms) | 38.64 µs (37.95–38.70 µs) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| v2_subscription/distinct_plans/1000 | 558.3 µs (553.0–567.1) | 103.5 µs (101.1–111.8) |
| v2_subscription/shared_plan/1000 | 237.2 µs (236.9–239.7) | 66.29 µs (66.12–71.04) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| serializers_cold/v1 | 6.490 µs (6.234–6.543) | 2.845 µs (2.724–2.853) |
| serializers_cold/v2 | 12.79 µs (12.75–13.09) | 4.248 µs (3.859–4.610) |
| serializers_cold/v2_precise | 3.855 µs (3.847–3.886) | 2.642 µs (2.411–2.667) |
| serializers_cold/stream_companion | 9.410 µs (9.316–9.505) | 3.751 µs (3.044–4.777) |
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| http_v2/cold_connection | 359.5 µs (358.1–363.5) | 370.1 µs (359.7–387.8) |
| http_v2/keep_alive | 67.29 µs (67.23–73.41) | 69.70 µs (67.84–70.14) |
| http_v2/dispatch_only | 621.8 ns (613.9–924.2) | 635.8 ns (625.6–636.0) |
Details · What changed, and what these numbers don't show
- Regular reader: batching reads whole spans rather than individual fields. Linux fixtures make 21–72 backend calls per capture instead of 135–314 (lazer gameplay: 28 calls / 5,418 bytes against 268 / 1,889). This requests more bytes while making far fewer calls.
- Windows batching:
read_manyissues oneReadProcessMemoryper run of ascending requests within a 4 KiB page, including gaps, plus a read for any short suffix. A backend call may still make several native reads; native read counts were not measured. The regular-reader synthetic harness is Linux-only; the live Windows rows below measure the combined effect. - Filtered WebSocket fan-out: production projection and in-process fan-out use changing snapshots, a paused Tokio clock and reference byte comparisons. Identical ordered filter plans share a broadcast-pass cache (at most 64 variants / 1 MiB); properties shared across distinct plans have a work budget.
- HTTP: the HTTP path was not optimized; the microbenchmarks are 2–6% slower on both platforms, within or near their ranges. New-connection Windows requests cost about 360–370 µs.
- These are synthetic fixtures, not live clients, network transport, or whole-daemon CPU and memory. The live measurements below are separate runs.
| Measurement | vosu 1.0.2 | vosu 1.1.0 |
|---|---|---|
| lazer gameplay | 268 calls | 28 calls |
| lazer menu | 314 calls | 72 calls |
| stable gameplay | 135 calls | 29 calls |
| stable menu | 148 calls | 21 calls |
Setup
| Item | Details |
|---|---|
| Builds | vosu 1.1.0 c791512, built with Rust 1.96.1 and each platform's release features; tosu v4.26.2 published assets; fresh per-run copies |
| Settings | POLL_RATE 150, PRECISE_DATA_POLL_RATE 10, pp calculation and key overlay on, loopback-only listeners, automatic updates off, tosu's in-game overlay off, warmed vosu lazer offsets cache; ENABLE_HIT_OFFSETS and ENABLE_MANIA_KEY_HIT_ERRORS off except the explicit cost run |
| Workload | One silent 25-minute map with 6001 circles, played by Autoplay in the osu! ruleset on lazer 2026.1005.0 and stable b20260924.1 |
| Host | Ryzen 9 9950X3D, RTX 5090 passed through to one guest at a time |
| Windows guest | Windows 11 IoT Enterprise LTSC 26100, 8 logical processors |
| Linux guest | Arch Linux, linux-zen 7.1.4, 8 vCPUs pinned to the V-cache CCD, 24 GiB; clients on headless labwc (Vulkan) through Xwayland; osu!stable through osu-winello's Wine 11.8 Staging, with vosu and tosu running as native Linux processes outside the Wine prefix |
Live readers
Each reader attached directly to the playing client with no daemon running, alternating vosu and tosu for five invocations each. A bar is the median of the five invocation medians; the range in parentheses spans those medians. Setup time is excluded from the cycle times and charted separately.
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer | 737.0 µs (729.2–741.5) | 148.0 µs (145.1–149.8) |
| Windows stable | 456.2 µs (448.6–472.9) | 132.7 µs (131.7–135.3) |
| Linux lazer | 147.1 µs (138.1–183.1) | 20.2 µs (17.8–21.3) |
| Linux stable (Wine) | 189.6 µs (182.2–232.7) | 33.7 µs (31.8–36.3) |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer | 151.2 µs (150.2–152.5) | 30.0 µs (29.8–31.0) |
| Windows stable | 40.7 µs (40.6–42.0) | 23.9 µs (23.8–24.3) |
| Linux lazer | 32.8 µs (31.8–39.8) | 9.1 µs (8.5–10.2) |
| Linux stable (Wine) | 13.9 µs (11.8–16.9) | 8.5 µs (7.6–9.4) |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer | 1521 ms | 71 ms |
| Windows stable | 589 ms | 85 ms |
| Linux lazer | 3972 ms | 61 ms |
| Linux stable (Wine) | 286 ms | 22 ms |
Details · What these runs do and don't compare
- Both readers ran their production capture paths with zero read errors in every invocation, but they don't read identical field sets: the cycles compare equivalent production work, not identical work.
- On Linux lazer, tosu's ranked-play read returned its not-ready sentinel on every regular cycle (counted, not an error). The cycle still continued through settings, gameplay, leaderboard, and user reads, 504 reads per cycle.
- Batched captures closed the Linux settings gap. Instrumented lazer captures read settings in 9 vosu backend calls (8.3 µs) against 243 tosu API calls (67.8 µs); the regular cycle was 24 calls (19.2 µs) against 504 (155.0 µs). Stable was 24 calls (32.2 µs) against 306 (169.4 µs). These include instrumentation overhead, unlike the charts. The call units differ, neither counts syscalls, and tosu string API calls hide a second native read.
- For Linux osu!stable, the tosu harness's own 32-bit process check was relaxed: Wine runs the
32-bit
osu!.exeinside a 64-bit process, and tosu's instance manager doesn't make that check.
Stable precise reads: 1.1.0 reads replay frames on every precise cycle, in batches, to
derive keys and hit errors in every ruleset. Five alternating pairs of candidate fe3201c
(before this change) and c791512 measured 6.68 → 8.42 µs on Linux (1.26×) and
20.22 → 24.74 µs on Windows (1.22×). Regular cycles did not change; lazer precise is
unaffected. These are separate same-process pairs, not the tosu comparison above.
Daemon CPU and memory
A psutil collector sampled each daemon's process tree once per second after 30 s of warm-up, for
three 45 s windows per mode. background mode made one /json/v2 request at the start and
end of each window on a new connection; consumer mode requested /json/v2 at 10 Hz over
keep-alive. Values are medians over the three windows. vosu alone ran by itself; the other
bars come from vosu and tosu running together.
| Measurement | tosu 4.26.2 | vosu | vosu alone |
|---|---|---|---|
| Windows lazer · background | 2.78% | 1.67% | 1.67% |
| Windows lazer · consumer | 2.64% | 1.70% | 1.49% |
| Windows stable · background | 1.63% | 1.53% | 1.49% |
| Windows stable · consumer | 3.19% | 1.81% | 1.70% |
| Linux lazer · background | 1.42% | 0.84% | 0.89% |
| Linux lazer · consumer | 2.53% | 0.96% | 0.96% |
| Linux stable (Wine) · background | 1.04% | 0.96% | 1.00% |
| Linux stable (Wine) · consumer | 2.27% | 1.07% | 1.11% |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer · background | 88.8 MB | 41.7 MB |
| Windows lazer · consumer | 91.2 MB | 42.2 MB |
| Windows stable · background | 148.9 MB | 49.7 MB |
| Windows stable · consumer | 152.7 MB | 50.9 MB |
| Linux lazer · background | 266.2 MB | 29.8 MB |
| Linux lazer · consumer | 276.1 MB | 31.0 MB |
| Linux stable (Wine) · background | 266.6 MB | 39.7 MB |
| Linux stable (Wine) · consumer | 274.7 MB | 40.5 MB |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer · background | 78.6 MB | 7.1 MB |
| Windows lazer · consumer | 82.7 MB | 7.9 MB |
| Windows stable · background | 131.5 MB | 14.7 MB |
| Windows stable · consumer | 135.7 MB | 16.0 MB |
| Linux lazer · background | 256.1 MB | 25.9 MB |
| Linux lazer · consumer | 266.1 MB | 27.2 MB |
| Linux stable (Wine) · background | 257.7 MB | 35.8 MB |
| Linux stable (Wine) · consumer | 265.8 MB | 36.6 MB |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows lazer · background | 10.45 ms | 9.90 ms |
| Windows lazer · consumer | 0.68 ms | 0.30 ms |
| Windows stable · background | 8.00 ms | 4.83 ms |
| Windows stable · consumer | 3.43 ms | 0.36 ms |
| Linux lazer · background | 3.25 ms | 0.77 ms |
| Linux lazer · consumer | 2.61 ms | 0.25 ms |
| Linux stable (Wine) · background | 4.42 ms | 0.80 ms |
| Linux stable (Wine) · consumer | 3.06 ms | 0.29 ms |
Details · Reading these numbers
- CPU is a percentage of one logical core.
- Resident memory is the Windows working set or the Linux resident set.
- Private memory is Windows private commit or Linux
Private_Clean + Private_Dirty + Private_Hugetlb, so it is not comparable across platforms. - Background latency covers only two cold requests per window, each on a new connection, so it mostly measures connection setup.
- tosu 4.26.2 publishes empty play data for osu-winello osu!stable when it isn't started from the
osu! folder: it resolves Wine's
D:\osu!.execommand line against its own working directory and can't open the map. The Linux osu!stable rows started tosu from the osu! folder, without changing tosu.
ENABLE_HIT_OFFSETS cost
A separate Linux lazer vosu-alone run enabled ENABLE_HIT_OFFSETS = true before warm-up,
on a fresh Autoplay of the same map in the same process. /json/v2 published 432 hit-offset
entries at the start and 5,853 at the end; all six windows were accepted.
| Linux lazer, vosu alone | Mode | CPU | RSS | Private | /json/v2 latency |
|---|---|---|---|---|---|
ENABLE_HIT_OFFSETS off (default) |
background | 0.89% | 37.1 MB | 33.3 MB | 0.56 ms |
ENABLE_HIT_OFFSETS on |
background | 0.91% | 37.2 MB | 33.4 MB | 0.69 ms |
ENABLE_HIT_OFFSETS off (default) |
consumer | 0.96% | 38.5 MB | 34.7 MB | 0.24 ms |
ENABLE_HIT_OFFSETS on |
consumer | 1.16% | 38.9 MB | 35.0 MB | 0.39 ms |
Enabling it adds precise-reader offset reads and the growing whole offset list to every
/json/v2 response. The consumer difference was not split between those costs. These
vosu-alone memory values are separate from the simultaneous-daemon charts.
Hot paths
These latest hot-path rows used vosu v1.0.0 on 2026-10-11, not 1.1.0, on idle guests before any client started. vosu used Criterion on that release commit. The tosu harness gives each case at least 3 s of warm-up and 100 equally weighted samples of about 50 ms, reporting the mean; that is Criterion-like, not Criterion. Bars are means per iteration. Each chart has its own scale.
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 1.603 ms | 195.934 µs |
| Linux | 1.069 ms | 62.559 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Linux | 991.577 ns | 304.825 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 332.630 µs | 17.344 µs |
| Linux | 227.061 µs | 14.172 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 437.981 µs | 14.608 µs |
| Linux | 252.084 µs | 14.567 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 41.892 µs | 2.309 µs |
| Linux | 37.245 µs | 1.628 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 400.973 µs | 5.895 µs |
| Linux | 206.320 µs | 6.082 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 18.604 µs | 337.148 ns |
| Linux | 8.095 µs | 219.466 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 9.558 µs | 11.500 µs |
| Linux | 7.673 µs | 7.193 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 11.319 µs | 8.084 µs |
| Linux | 9.269 µs | 4.671 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 16.640 µs | 13.639 µs |
| Linux | 13.710 µs | 11.781 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 888.088 ns | 4.866 µs |
| Linux | 863.276 ns | 3.528 µs |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 1.035 µs | 400.119 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 8.169 µs | 436.657 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 8.156 µs | 439.031 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 1.028 µs | 399.726 ns |
| Measurement | tosu 4.26.2 | vosu |
|---|---|---|
| Windows | 8.207 µs | 1.053 µs |
Details · What these rows exercise
The rows exercise the closest tosu production path, not identical work:
- tosu's map calculation goes through its native lazer calculator (
0.6.1-20260729-main.0), including the JavaScript bridge. - tosu's raw-snapshot cases take error and not-ready paths on the zeroed fixture, and its lazer case rescans because the fixture fails its GameBase check.
batch_scancalls tosu's inner scanner through an adapter, not its process-wide scan.- tosu has no batched read API, so the read-many cases issue eight reads, and every read allocates a returned buffer.
- tosu's precise serializer surfaces four keys; vosu's fixture has 18. The serializer inputs
differ in general, which is part of why
serializers_cold/v2_precisefavors tosu. - On Windows, vosu's
serializers_cold/v1andstream_companionintervals are wide (6.3–11.6 µs and 9.6–15.1 µs). linux_process_memoryandwindows_process_memoryonly exist on their own platform.
Reproduce
Commands, fixtures, and the live-reader example are in the
benchmark guide.
The tosu-side harness lives outside the vosu repository; it bundles tosu commit b21b452 with
benchmark entry points that call the unchanged production functions. Launch identities, collector
configurations, per-window samples, and reader logs are kept with the measurement evidence.