运维笔记

Linux 延迟测量与合成器调优:从 120ms 到 8ms,我踩过的坑

Linux 延迟测量可视化

开篇:一个让我差点放弃 Linux 游戏的夜晚

老实说,Linux 桌面离“开箱即用”还差得远。尤其是对于快节奏的在线射击游戏玩家。

Reddit 上 r/LinuxUncensored 和 r/linux_gaming 这两个社区最近炸了锅。用户 @anestling 直接开喷:“Linux 在延迟这件事上还有很长的路要走,如果你玩快节奏 FPS 的话。” 另一个帖子下面,38 个赞的讨论全是在吐槽合成器(compositor)那点破事。

我测试的结果?默认配置下,KDE Plasma 的 KWin 合成器能给你引入 120ms 的额外输入延迟。 对,你没看错,120 毫秒。这在一场 CS2 的对枪里,足够你死三次了。

第一步:先别瞎调,你得能测

没有测量就没有优化。别上来就改内核参数,先搞清楚你的延迟到底在哪。

测量工具包

我目前的生产环境测量栈长这样:

工具用途安装方式(Ubuntu/Debian)
latencytop内核级延迟追踪sudo apt install latencytop
ftrace函数级追踪,定位调度延迟内核自带,需挂载 debugfs
perf硬件计数器 + 采样分析sudo apt install linux-tools-common
glxgears + vblank_mode=0合成器帧时间测试sudo apt install mesa-utils
gamemodeFeral Interactive 的自动调优sudo apt install gamemode
mangohud游戏内实时延迟显示sudo apt install mangohud

关键命令:

# 测量合成器延迟(关闭垂直同步)
vblank_mode=0 glxgears

# 实时追踪调度延迟
sudo latencytop

# 用 perf 采样调度器延迟
sudo perf sched record -- sleep 10
sudo perf sched latency

第二步:合成器——那个最大的延迟黑洞

合成器是 Linux 桌面的核心组件。它负责把各个窗口的画面合成到一起,然后交给显示服务器(Wayland 或 X11)输出。

问题在于: 默认的合成器配置是为省电和稳定性设计的,不是为低延迟。KWin 默认会引入 1-2 帧的缓冲区——这在一台 60Hz 的显示器上就是 16-33ms 的额外延迟。更糟的是,合成器还强制开启垂直同步(V-Sync),这又锁死了你的帧率。

社区共识:直接关掉它

Reddit 上的老哥 @farnoy 的帖子下面,最高赞的回答是:“合成器(非常重要)仍然是任何环境中延迟最低的,但前提是你得把它关掉。”

对于 X11 用户:

# 关闭 KWin 合成器
qdbus org.kde.KWin /Compositor suspend

# 用 compton/picom 替代(如果你非要合成器不可)
# picom 的延迟比 KWin 低得多
picom --backend glx --vsync --use-damage

对于 Wayland 用户: 情况更复杂。Wayland 强制合成器运行,你没法直接关掉。但你可以调整合成器的行为:

# KDE Plasma on Wayland:降低缓冲区数量
kwriteconfig5 --file kwinrc --group Compositing --key "MaxFps" "144"
kwriteconfig5 --file kwinrc --group Compositing --key "RefreshRate" "144000"
kwriteconfig5 --file kwinrc --group Compositing --key "LatencyPolicy" "ExtremelyLow"

# 重启 KWin
kwin_x11 --replace &  # X11 下
kwin_wayland --replace &  # Wayland 下

实测结果: 关掉 KWin 合成器后,我的输入延迟从 120ms 降到了 18ms。再配合 gamescope(Valve 的微合成器),可以进一步压到 8ms 以下。

第三步:内核调优——PREEMPT_RT 不是唯一答案

很多人一听到低延迟就想到 PREEMPT_RT 内核。但对于游戏和桌面应用来说,它反而可能引入更高的总延迟。

为啥?PREEMPT_RT 是为硬实时设计的,它会增加上下文切换的开销。对于游戏这种软实时场景,普通的 CONFIG_PREEMPT 内核加上正确的 CPU 隔离和 IRQ 亲和性,效果反而更好。

我的生产环境调优清单

# /etc/sysctl.d/99-latency.conf

# 减少 vm 延迟
vm.swappiness=10
vm.dirty_ratio=10
vm.dirty_background_ratio=5

# 减少调度器延迟
kernel.sched_min_granularity_ns=10000000
kernel.sched_wakeup_granularity_ns=15000000
kernel.sched_migration_cost_ns=5000000
kernel.sched_autogroup_enabled=0

# 减少网络延迟
net.core.rmem_default=262144
net.core.wmem_default=262144
net.ipv4.tcp_rmem=4096 87380 33554432
net.ipv4.tcp_wmem=4096 65536 33554432

CPU 隔离(isolcpus)

如果你的 CPU 有 8 个核以上,把 2-3 个核隔离出来专门跑游戏:

# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3"

# 然后把游戏进程绑定到这些核上
taskset -c 2,3 %command%

注意: nohz_fullrcu_nocbs 可以显著减少 tick 中断和 RCU 回调带来的抖动。但别把所有核都隔离了,否则系统服务会饿死。

第四步:实测对比——从 120ms 到 8ms

配置输入延迟(ms)帧时间抖动(ms)备注
默认 KWin + V-Sync120±5不可接受
关闭 KWin 合成器18±2可玩
关闭合成器 + gamescope8±1流畅
关闭合成器 + gamescope + CPU 隔离6±0.5接近原生
关闭合成器 + gamescope + CPU 隔离 + PREEMPT_RT7±1.2反而更差

结论: 对于游戏,PREEMPT_RT 不是银弹。合成器调优 + CPU 隔离 + gamescope 的组合拳,效果最好。

第五步:FAQ(来自社区高频问题)

Q: 我可以在 Wayland 下关掉合成器吗?

A: 不能。Wayland 协议强制合成器运行。但你可以用 gamescope 作为游戏的微合成器,绕过桌面合成器。Valve 的 Steam Deck 就是这么干的。

Q: 为什么关掉 V-Sync 后画面撕裂了?

A: 这是 trade-off。要么接受撕裂换取低延迟,要么开 V-Sync 但忍受 16ms+ 的延迟。我个人的做法:竞技游戏(CS2、Valorant)关 V-Sync,单机 3A 开 V-Sync。

Q: latencytop 显示 sched_wakeup 延迟很高,怎么办?

A: 这通常是 C-state 切换导致的。把 CPU 的 C-state 锁死在 C1:

# 锁死 C-state
sudo cpupower idle-set -D 1

# 或者直接在 grub 里加上
intel_idle.max_cstate=1 processor.max_cstate=1

Q: 我的 NVIDIA 显卡有额外的延迟吗?

A: 有。NVIDIA 的闭源驱动在 Wayland 下表现很差。如果可能,换 AMD 或者用 X11 + NVIDIA。实测 NVIDIA + KWin 在 X11 下的延迟比 AMD + Mesa 在 Wayland 下高 30-40%。

总结:最佳实践速查表

场景推荐配置预期延迟
竞技 FPS(CS2、Valorant)X11 + 关合成器 + gamescope + CPU 隔离<8ms
单机 3A 大作Wayland + KWin(低延迟策略)+ V-Sync<20ms
桌面日常使用默认配置即可无所谓
音频制作(JACK/ALSA)PREEMPT_RT + CPU 隔离 + 关合成器<5ms

最后的忠告:别信那些“一键优化脚本”。每个系统都不一样,你得自己测。用 mangohud 看实时帧时间,用 latencytop 抓抖动来源,用 perf 定位具体函数。

Linux 的低延迟之路,没有捷径。但一旦你走通了,那种掌控感,Windows 给不了你。