开篇:一个让我差点放弃 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 |
gamemode | Feral 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_full 和 rcu_nocbs 可以显著减少 tick 中断和 RCU 回调带来的抖动。但别把所有核都隔离了,否则系统服务会饿死。
第四步:实测对比——从 120ms 到 8ms
| 配置 | 输入延迟(ms) | 帧时间抖动(ms) | 备注 |
|---|---|---|---|
| 默认 KWin + V-Sync | 120 | ±5 | 不可接受 |
| 关闭 KWin 合成器 | 18 | ±2 | 可玩 |
| 关闭合成器 + gamescope | 8 | ±1 | 流畅 |
| 关闭合成器 + gamescope + CPU 隔离 | 6 | ±0.5 | 接近原生 |
| 关闭合成器 + gamescope + CPU 隔离 + PREEMPT_RT | 7 | ±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 给不了你。