Skip to content
HN On Hacker News ↗

Measuring input latency on Linux: X11 vs Wayland, VRR, and DXVK

▲ 407 points 290 comments by hoechst 1mo ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is fully human-written

1 %

AI likelihood · overall

Human
100% human-written 0% AI-generated
SEGMENTS · HUMAN 6 of 6
SEGMENTS · AI 0 of 6
WORD COUNT 1,621
PEAK AI % 1% · §5
Analyzed
Jul 14
backend: pangram/v3.3
Segments scanned
6 windows
avg 270 words each
Distribution
100 / 0%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 1,621 words · 6 segments analyzed

Human AI-generated
§1 Human · 0%

2026-07-13Two years ago, I switched to Linux on my gaming PC. People kept telling me that it could perform way better than Windows when it comes to FPS, frame pacing and input latency, and when I tried it out, it did feel a lot better. The internet is full of advice on optimizing Linux for gaming:

Wayland has bad input lag, use X11 Disable compositing (“use flip mode”) Use a latency-optimized DXVK fork Use a gaming-specific kernel scheduler etc.

I play competitive FPS games, so low latency, consistent frame times and high FPS matter to me. On Linux, there are countless settings to tweak for this (magic env vars, gamescope, gamemode, even more DXVK forks, and so on). But it always bothered me that I did not have a reliable way to verify whether something actually lowered the system latency or if it was just snake oil, a placebo effect, or actually worse without me realizing it.

The device The idea is simple: Strap a device with some kind of light sensor onto a monitor and connect it via USB to the PC to simulate mouse clicks. On click, measure the time between the click and the moment the light sensor detects a change on the screen. This way, you measure the end-to-end system latency. © NVIDIA has a picture that summarizes this quite nicely. While there are now a couple of open source devices like this available, like m2p-latency or the Open-Source-LDAT, when I started this side project, there was just the OSLTT, and knowing nothing about hardware, I was happy to study its schematics and loosely base my design on it. But finishing my project just this month, I ended up integrating a lot of ideas from the other two projects as well.

To make a long story short, I learned a lot about microcontrollers, soldering, Arduino firmware development, integration time, transimpedance amplifiers, KiCad (just a little) and enclosure design. Here’s what I landed on:

An Adafruit QT Py RP2040 acts as a USB HID mouse with 1000 Hz polling rate and fires a click. The moment the click is sent, it starts collecting samples from the photodiode (every ~24 µs).

§2 Human · 0%

12,000 samples per click are streamed over serial to the host and logged to a CSV. Based on the samples, a tool on the host establishes a per-click baseline, then finds the first sample that deviates a certain amount from the baseline. Because the time it takes to collect 12k samples is fixed, it can now calculate the time between sending the click and detecting a brightness change on the screen.

Test scenarios I wanted to test three different things. Display server (X11 vs Native Wayland) A lot of people still use X11 over Wayland because Wayland is said to have much worse input lag. Just searching for it, there are a lot of people complaining that Wayland “feels off”. VRR (on vs off) Variable Refresh Rate / G-Sync / FreeSync / Whatever you want to call it. Also highly debated. DXVK low-latency fork (on vs off) Referred to as dxvk-low-latency or low-latency from now on. The maintainer of this fork, netborg, put a lot of effort into developing this frame pacer and it recently got integrated into the official proton-cachyos package, enabled via the env var PROTON_DXVK_LOWLATENCY=1. This fork’s promises were one of the deciding factors in me wanting to try out desktop Linux again. Bonus: dxvk-low-latency vs default dxvk uncapped The biggest advantages a frame pacer like dxvk-low-latency brings are to absorb frame time fluctuations and to prevent render-queue buildup. With the testing method I used (a static in-game scene, see below for more), there were no frame time fluctuations to observe, as all tests produced purely CPU-bound scenarios. But this mostly does not reflect a real gaming session, where frame times can fluctuate because of what happens in-game or outside the game (e.g. other processes using resources). So to show the pacer at work I added two uncapped test cases. Bonus: Native Wayland vs XWayland I ran all Wayland test cases via native Wayland (PROTON_ENABLE_WAYLAND=1) as I was already aware that XWayland would introduce lag. But for the sake of comparison, I added two XWayland test cases (only with VRR off).

§3 Human · 0%

Test conditions

HardwareAMD Ryzen 7 5800X3DNVIDIA GeForce RTX 4070 SUPER2x8 GB DDR4 at 3200 MHzMSI MAG 272QP QD-OLED X50 at 2560×1440 / 500 HzMSI B450 GAMING PRO CARBON AC Only one display was connected during the tests.

SoftwareVersionCachyOS-Kernel7.1.3-2-cachyosNVIDIA driver610.43.03-1KDE Plasma6.7.2-1.1xorg-server21.1.24-1.1proton-cachyos-native1:11.0.20260602-3dxvk (via proton-cachyos)3.0 The default CachyOS kernel scheduler was used.

System Settings

500 Hz refresh rate in system settings Flip mode on X11: Enabled via nvidia-settings Flip mode on Wayland: Confirmed to be enabled (see below how) VRR on X11: Enabled via nvidia-settings (changing this requires a reboot) VRR on Wayland: Enabled via KDE Settings Menu (no reboot needed)

Flip mode (or “direct scanout”) vs Blit mode (compositing) on Wayland: There is no setting for it. The compositor decides by itself whether it composites a frame or uses direct scanout. To make sure the game is running in flip mode: Open “KWin Debug Console” (it’s a GUI tool) and in the “Effects” tab, enable showcompositing. Then make sure the game is fully focused and the only thing on screen in fullscreen mode. If there’s no red border visible around the edges of the game, it’s in Flip mode.

§4 Human · 0%

dxvk To make the comparison fair, an optimized dxvk.conf was used depending on the scenario:

If VRR was disabled, dxgi.maxFrameRate = 500 was set (FPS capped at the screen’s refresh rate) If VRR was enabled and dxvk-low-latency was disabled, dxgi.maxFrameRate = 497 was set (FPS capped slightly below screen refresh rate) If VRR was enabled and dxvk-low-latency was enabled, the following was used to utilize the low latency VRR frame pacing:

dxgi.maxFrameRate = 480 dxvk.lowLatencyOffset = 70 dxvk.framePace = "low-latency-vrr-500" dxvk.lowLatencyAllowCpuFramesOverlap = False In all cases, d3d11.cachedDynamicResources = "c" was set.

Game and Methodology The game I used is Diabotical, a DirectX 11 game, launched through Heroic with Proton. Game settings

Native screen resolution 100% render scale Vsync off Every other video setting as low as possible

There is a hidden command that hides the UI for a short amount of time. Binding that command to left click (/bind mouse_left testlatency) and setting up a HUD that would display a large white box, I was able to produce large brightness differences on click. The device at work in Diabotical. Methodology

Close unnecessary software. Launch the game. Start a local match server (same mode and map every time). Move to a specific spot, put the mouse onto a specific landmark. Run the test case iteration (100 clicks, runs for about 2 minutes). Once the test is done, start the next test case iteration (3 in total). In-game conditions: No bots, no other players, no movement, no round restarts. It is basically just a static scene that will stay like this indefinitely. System conditions: During testing, no other significant processes should be running on the system. The measuring device remained in the same position (see the video) across all tests.

§5 Human · 1%

Results click2photon latency: X11 / Wayland, VRR, low-latencyDiabotical, 500 Hz QD-OLED, RTX 4070 SUPER, 300 clicks per case. Every capped test case held its frame rate cap stable during testing and the game remained CPU-bound throughout. The data seems clean: No test case produced wild outliers and every case produced a bell-shaped distribution, roughly 2 to 3 ms wide between p5 and p95. Three things jump out:

The 8 main cases all land within 0.72 ms of each other (medians from 4.21 ms to 4.93 ms). XWayland adds 3.13 ms on top of its native Wayland equivalent (8.06 ms vs 4.93 ms median). In the uncapped cases, the dxvk fork managed to reduce latency by 0.84 ms.

Here is the fastest case: Latency distribution: fastest case (X11, VRR, low-latency)

X11 vs Wayland So, does X11 have lower latency than Wayland? Yes, but nowhere near enough to explain why Wayland is generally perceived as much worse than X11.

ConfigurationX11WaylandDifferencelow-latency + VRR4.21 ms4.38 ms+0.17 mslow-latency4.64 ms4.83 ms+0.19 msVRR4.45 ms4.67 ms+0.22 msplain4.79 ms4.93 ms+0.14 ms X11 wins in each scenario, but it is just a 0.14 to 0.22 ms difference. The distribution is very similar: Latency distribution: plain X11 vs plain Wayland ---https://news.ycombinator.com/ VRR: on or off? VRR has the biggest impact across the pairings: enabling it is 0.26 to 0.45 ms faster than leaving it disabled.

§6 Human · 1%

ConfigurationVRR offVRR onDifferenceX11, low-latency4.64 ms4.21 ms-0.43 msX114.79 ms4.45 ms-0.34 msWayland, low-latency4.83 ms4.38 ms-0.45 msWayland4.93 ms4.67 ms-0.26 ms It also flattens the distribution: the p95-p5 spread is 2.1 to 2.2 ms in the VRR cases versus 2.6 to 3.0 ms without VRR. Latency distribution: VRR on vs VRR off (Wayland, low-latency) That’s consistent with how VRR works: frames scan out when they are ready instead of waiting for the next scanout slot.

dxvk-low-latency is good In the capped test cases, the difference is small but consistent and of about the same magnitude as X11 vs Wayland. Where the difference between Wayland and X11 is on average 0.18 ms, using dxvk-low-latency is on average 0.20 ms faster.

Configurationlow-latency offlow-latency onDifferenceX11, VRR4.45 ms4.21 ms-0.24 msX114.79 ms4.64 ms-0.15 msWayland, VRR4.67 ms4.38 ms-0.29 msWayland4.93 ms4.83 ms-0.10 ms

In the uncapped test cases, we can get an idea of where the real strength of dxvk-low-latency lies: smoothing out uneven frame pacing and preventing render-queue buildup. The pacer does this by making sure the GPU is never fully utilized, so the game is always close to GPU-bound, but never entirely. This could be observed in the test runs, where GPU utilization was at 95-97% with dxvk-low-latency and at 100% without it. This comes at a small price in the form of FPS.