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.

Linux · regular_reader · lower is better
Measurementvosu 1.0.2vosu 1.1.0
regular_reader/lazer_gameplay92.27 µs
(91.63–126.40)
16.66 µs
(16.43–16.68)
regular_reader/lazer_menu108.19 µs
(107.58–123.73)
29.79 µs
(29.42–29.86)
regular_reader/stable_gameplay45.71 µs
(45.27–45.71)
12.70 µs
(12.42–12.73)
regular_reader/stable_menu49.11 µs
(48.74–49.35)
10.58 µs
(10.31–10.63)
Linux · memory_reader_bench · lower is better
Measurementvosu 1.0.2vosu 1.1.0
memory_reader_bench (lazer precise capture)10.64 µs
(10.44–10.97)
8.789 µs
(8.687–8.959)
Linux · filtered_projection · lower is better
Measurementvosu 1.0.2vosu 1.1.0
filtered_projection/v2_identical/1006.179 ms
(6.151–6.434 ms)
19.90 µs
(19.84–19.96 µs)
filtered_projection/v2_unique/1006.950 ms
(6.796–7.194 ms)
31.71 µs
(31.61–31.72 µs)
Linux · v2_subscription · lower is better
Measurementvosu 1.0.2vosu 1.1.0
v2_subscription/distinct_plans/1000409.1 µs
(409.0–435.8)
85.58 µs
(85.27–86.55)
v2_subscription/shared_plan/1000209.2 µs
(208.4–209.2)
61.28 µs
(59.84–61.41)
Linux · serializers_cold · lower is better
Measurementvosu 1.0.2vosu 1.1.0
serializers_cold/v14.450 µs
(4.437–5.939)
2.647 µs
(2.639–2.818)
serializers_cold/v210.54 µs
(10.41–10.69)
3.953 µs
(3.907–4.158)
serializers_cold/v2_precise3.914 µs
(3.881–3.990)
2.718 µs
(2.690–2.954)
serializers_cold/stream_companion6.527 µs
(6.501–6.539)
3.230 µs
(3.162–3.250)
Linux · http_v2 · lower is better
Measurementvosu 1.0.2vosu 1.1.0
http_v2/cold_connection45.38 µs
(43.85–46.49)
48.20 µs
(45.24–54.50)
http_v2/keep_alive5.575 µs
(5.540–5.618)
5.710 µs
(5.634–5.735)
http_v2/dispatch_only364.3 ns
(354.9–374.4)
381.4 ns
(380.3–382.1)
Windows · memory_reader_bench · lower is better
Measurementvosu 1.0.2vosu 1.1.0
memory_reader_bench (lazer precise capture)19.10 µs
(18.97–24.02)
19.14 µs
(18.97–19.46)
Windows · filtered_projection · lower is better
Measurementvosu 1.0.2vosu 1.1.0
filtered_projection/v2_identical/1007.679 ms
(7.656–7.713 ms)
25.32 µs
(24.96–25.42 µs)
filtered_projection/v2_unique/1007.688 ms
(7.646–7.900 ms)
38.64 µs
(37.95–38.70 µs)
Windows · v2_subscription · lower is better
Measurementvosu 1.0.2vosu 1.1.0
v2_subscription/distinct_plans/1000558.3 µs
(553.0–567.1)
103.5 µs
(101.1–111.8)
v2_subscription/shared_plan/1000237.2 µs
(236.9–239.7)
66.29 µs
(66.12–71.04)
Windows · serializers_cold · lower is better
Measurementvosu 1.0.2vosu 1.1.0
serializers_cold/v16.490 µs
(6.234–6.543)
2.845 µs
(2.724–2.853)
serializers_cold/v212.79 µs
(12.75–13.09)
4.248 µs
(3.859–4.610)
serializers_cold/v2_precise3.855 µs
(3.847–3.886)
2.642 µs
(2.411–2.667)
serializers_cold/stream_companion9.410 µs
(9.316–9.505)
3.751 µs
(3.044–4.777)
Windows · http_v2 · lower is better
Measurementvosu 1.0.2vosu 1.1.0
http_v2/cold_connection359.5 µs
(358.1–363.5)
370.1 µs
(359.7–387.8)
http_v2/keep_alive67.29 µs
(67.23–73.41)
69.70 µs
(67.84–70.14)
http_v2/dispatch_only621.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_many issues one ReadProcessMemory per 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.
Linux native backend calls per regular capture · lower is better
Measurementvosu 1.0.2vosu 1.1.0
lazer gameplay268 calls28 calls
lazer menu314 calls72 calls
stable gameplay135 calls29 calls
stable menu148 calls21 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.

Regular cycle · lower is better
Measurementtosu 4.26.2vosu
Windows lazer737.0 µs
(729.2–741.5)
148.0 µs
(145.1–149.8)
Windows stable456.2 µs
(448.6–472.9)
132.7 µs
(131.7–135.3)
Linux lazer147.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)
Precise cycle · lower is better
Measurementtosu 4.26.2vosu
Windows lazer151.2 µs
(150.2–152.5)
30.0 µs
(29.8–31.0)
Windows stable40.7 µs
(40.6–42.0)
23.9 µs
(23.8–24.3)
Linux lazer32.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)
Setup · lower is better
Measurementtosu 4.26.2vosu
Windows lazer1521 ms71 ms
Windows stable589 ms85 ms
Linux lazer3972 ms61 ms
Linux stable (Wine)286 ms22 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!.exe inside 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.

CPU (% of one logical core) · lower is better
Measurementtosu 4.26.2vosuvosu alone
Windows lazer · background2.78%1.67%1.67%
Windows lazer · consumer2.64%1.70%1.49%
Windows stable · background1.63%1.53%1.49%
Windows stable · consumer3.19%1.81%1.70%
Linux lazer · background1.42%0.84%0.89%
Linux lazer · consumer2.53%0.96%0.96%
Linux stable (Wine) · background1.04%0.96%1.00%
Linux stable (Wine) · consumer2.27%1.07%1.11%
Resident memory (RSS / working set) · lower is better
Measurementtosu 4.26.2vosu
Windows lazer · background88.8 MB41.7 MB
Windows lazer · consumer91.2 MB42.2 MB
Windows stable · background148.9 MB49.7 MB
Windows stable · consumer152.7 MB50.9 MB
Linux lazer · background266.2 MB29.8 MB
Linux lazer · consumer276.1 MB31.0 MB
Linux stable (Wine) · background266.6 MB39.7 MB
Linux stable (Wine) · consumer274.7 MB40.5 MB
Private memory · lower is better
Measurementtosu 4.26.2vosu
Windows lazer · background78.6 MB7.1 MB
Windows lazer · consumer82.7 MB7.9 MB
Windows stable · background131.5 MB14.7 MB
Windows stable · consumer135.7 MB16.0 MB
Linux lazer · background256.1 MB25.9 MB
Linux lazer · consumer266.1 MB27.2 MB
Linux stable (Wine) · background257.7 MB35.8 MB
Linux stable (Wine) · consumer265.8 MB36.6 MB
/json/v2 latency · lower is better
Measurementtosu 4.26.2vosu
Windows lazer · background10.45 ms9.90 ms
Windows lazer · consumer0.68 ms0.30 ms
Windows stable · background8.00 ms4.83 ms
Windows stable · consumer3.43 ms0.36 ms
Linux lazer · background3.25 ms0.77 ms
Linux lazer · consumer2.61 ms0.25 ms
Linux stable (Wine) · background4.42 ms0.80 ms
Linux stable (Wine) · consumer3.06 ms0.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!.exe command 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.

batch_scan/three_patterns_2mib · lower is better
Measurementtosu 4.26.2vosu
Windows1.603 ms195.934 µs
Linux1.069 ms62.559 µs
linux_process_memory/current_process_64_bytes · lower is better
Measurementtosu 4.26.2vosu
Linux991.577 ns304.825 ns
map_calculation/full_difficulty_performance · lower is better
Measurementtosu 4.26.2vosu
Windows332.630 µs17.344 µs
Linux227.061 µs14.172 µs
map_calculation/gradual_all_objects · lower is better
Measurementtosu 4.26.2vosu
Windows437.981 µs14.608 µs
Linux252.084 µs14.567 µs
map_calculation/parse · lower is better
Measurementtosu 4.26.2vosu
Windows41.892 µs2.309 µs
Linux37.245 µs1.628 µs
raw_snapshot_reads/lazer_regular_fields · lower is better
Measurementtosu 4.26.2vosu
Windows400.973 µs5.895 µs
Linux206.320 µs6.082 µs
raw_snapshot_reads/stable_regular_fields · lower is better
Measurementtosu 4.26.2vosu
Windows18.604 µs337.148 ns
Linux8.095 µs219.466 ns
serializers_cold/stream_companion · lower is better
Measurementtosu 4.26.2vosu
Windows9.558 µs11.500 µs
Linux7.673 µs7.193 µs
serializers_cold/v1 · lower is better
Measurementtosu 4.26.2vosu
Windows11.319 µs8.084 µs
Linux9.269 µs4.671 µs
serializers_cold/v2 · lower is better
Measurementtosu 4.26.2vosu
Windows16.640 µs13.639 µs
Linux13.710 µs11.781 µs
serializers_cold/v2_precise · lower is better
Measurementtosu 4.26.2vosu
Windows888.088 ns4.866 µs
Linux863.276 ns3.528 µs
windows_process_memory/read_exact_64_bytes · lower is better
Measurementtosu 4.26.2vosu
Windows1.035 µs400.119 ns
windows_process_memory/read_many_contiguous_8x8_bytes · lower is better
Measurementtosu 4.26.2vosu
Windows8.169 µs436.657 ns
windows_process_memory/read_many_gapped_8x8_bytes · lower is better
Measurementtosu 4.26.2vosu
Windows8.156 µs439.031 ns
windows_process_memory/read_many_single_64_bytes · lower is better
Measurementtosu 4.26.2vosu
Windows1.028 µs399.726 ns
windows_process_memory/read_many_wide_8x8_bytes · lower is better
Measurementtosu 4.26.2vosu
Windows8.207 µs1.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_scan calls 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_precise favors tosu.
  • On Windows, vosu's serializers_cold/v1 and stream_companion intervals are wide (6.3–11.6 µs and 9.6–15.1 µs).
  • linux_process_memory and windows_process_memory only 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.

Edit this page on GitHub