1. Wayland时代还在用X11:Compton的适用场景与性能困境
1.1 Compton到底是什么,为什么老兵不死
很多接触Linux桌面不到两三年的朋友,可能压根没听说过Compton这个名字。它是X11环境下的一款合成管理器(compositor),负责给窗口加上阴影、圆角、半透明、切换动画和淡入淡出这类视觉效果。注意一个背景:X11窗口系统本身是把各个窗口的内容按区域往上绘制的,合成管理器在这中间多加了一层“先离屏绘制、再合成提交”的流程,所有视觉效果几乎都由它来完成。
Compton最初是为了替代老旧的xcompmgr出现的,一度在Openbox、i3这些轻量级窗口管理器用户里非常流行。后来社区维护慢慢转移到fork项目picom,但老配置里习惯叫的compton命令、compton.conf文件名在很长一段时间内仍然是兼容的。我自己现在用的发行版上,二进制还是picom,但配置文件沿用旧习惯,命令参数也基本兼容,所以下面内容里我混用这两个名字,但指的是一回事。
为什么这么多年还有人翻它的文档?因为X11没有死,而且短期内也死不了。远程X转发、某些专业软件、一部分老项目管理流程、以及大量还在跑的旧硬件,都绑定在X11上。在Wayland已经成为新装机默认会话的今天,X11下的体验优化话题反而显得稀缺,实际需要的人却一点不少。
1.2 Ubuntu 22.04用户回到X11的常见原因
最近看到“ubuntu22.04 wayland登录如何改为x11登录”这个关键词频繁出现,背后的原因我太熟悉了。默认Wayland会话看上去美好,但实际工作里有一批场景会让你不得不切回Xorg:
- 老旧的NVIDIA显卡,闭源驱动在Xwayland下的表现经常出现硬件光标消失、窗口闪烁、OpenGL程序帧率异常;
- Wine运行Windows应用时,很多游戏窗口在Wayland原生会话下无法正确获取输入焦点,切回X11后一切正常;
- 基于xdotool、xclip这类X11扩展的自动化脚本和工具链,在Wayland原生会话里直接失灵;
- 向日葵、ToDesk等远程协助工具长期以来只支持X11会话;
- 部分型号的触控板、多屏缩放在这种场景的驱动状态,在X11下反而更稳定。
搜索这个关键词的人,很大概率就是已经切回了X11,然后发现桌面滚动画布或者拖动窗口时有点黏糊。这时候你的目光自然会落到合成器上:Compton默认参数吃不吃性能?X Render后端能不能调得更好?这正是我写这篇东西的出发点。
1.3 为什么“合成性能”值得单独优化
可能有人觉得合成器不就是让窗口变个透明吗,能有多耗资源?这么想就低估了它的工作量。合成管理器在每一帧都要把所有窗口的内容整理成最终桌面图像。窗口越多、特效越复杂、屏幕分辨率越高,开销就越大。如果合成性能差,你感受到的不是某个特效变慢,而是整个桌面都像隔着一层水:滚动网页掉帧、视频全屏切换明显卡顿、拖动窗口时有拖影。
所以优化Compton的X Render后端,不是业余玩家抠参数找乐子,而是在老机器、虚拟机、无GPU加速的远程环境里实实在在提升桌面响应速度的手段。这篇文章我会把原理、配置、实测和环境坑一气讲完,适合手里正好有一台老机器、或刚切回X11会话觉得卡顿的读者。
2. X Render后端的工作机制与真实瓶颈
2.1 先搞清X11和X Render的关系
X11是协议,X Render(常写作XRender)是X11协议族里的渲染扩展,主要解决2D图形加速问题。X Render在X服务器上定义了一套“图片对象”和“绘制操作”的概念,能把缩放、混合、渐变、模糊这类常见操作下放到支持此扩展的实现中去跑。Xorg服务器自带的软件渲染路径就支持X Render,因此它在任何显卡驱动上都能工作。
启用合成管理器后,每个窗口的内容不再直接画到屏幕上,而是先画到后台的离屏缓冲(off-screen buffer),然后由合成管理器收集这些窗口内容,按上下层顺序做Alpha混合,最后把合成结果翻转到屏幕。X Render后端,就是这条合成链路里负责“最终合并图层”的那个模块:它调用X Render扩展的接口,把各窗口位图合成起来。
这一点可以类比成做多图层海报:普通X11是直接在成品纸上写字画画;启用合成器后,每层内容都先分别画在醋酸纸上,最后由一个人拿着所有醋酸纸对着光重叠成一张成品。X Render后端就是负责最后一次叠纸的人,而且是纯手工叠——后面这段话你可以留个印象,它能帮你理解很多性能问题。
2.2 X Render后端在合成链路里做了什么
Compton有几种后端:xrender、glx、dri3、egl(版本不同支持情况不同)。X Render后端完全走X服务器的软件渲染路径,不支持直接使用GPU加速的OpenGL纹理。它的工作方式大致是:
- 接收来自X服务器的Damage事件,得知哪个窗口的哪个区域发生了变化;
- 把需要更新的窗口内容当成pixmap(位图),提交给XServer做渲染;
- 对需要产生特殊效果的窗口,调用X Render的Convolve、Transform等操作生成阴影、模糊、半透明效果;
- 把所有图层合成到同一个后备缓冲,再一次性翻转到屏幕。
这里最关键的性能隐患在于“阴影”。阴影不是简单地给窗口黑色矩形加个透明度,而是在X Render环境下要做卷积模糊:把窗口轮廓外扩、逐像素计算周围像素的权重平均。窗口越复杂、面积越大,卷积计算量成倍增加。而高斯的近似卷积在软件实现里是相当典型的CPU密集操作。默认配置下,Compton给每个新窗口生成阴影,并且窗口移动时阴影会跟着重算。桌面上同时几十个窗口、不断切换和拖动时,CPU消耗就是这么涨上去的。
除了阴影,淡入淡出效果也会让合成器在效果持续的几百毫秒内连续多次重绘窗口内容,这在快速切换窗口时会感知为轻微卡顿。想要提升X Render后端的综合性能,基本思路就是减少这些CPU侧的高频重算。
2.3 定位瓶颈的准备步骤
改配置之前,建议先花十分钟观测现状,不然就是在黑灯情况下拧螺丝。我每次拿到一台卡顿的X11机器,都会先做这几件事:
- 用
xrandr --listmonitors确认当前分辨率和刷新率,4K@60下面X Render后端的开销比1080p大了远不止两倍; - 把Compton停掉跑一会儿,记录CPU和体感卡顿,再启动它跑一会儿,对比差异,确认瓶颈确实来自合成器;
- 用
pidstat -p <compton进程号> 1或者top观察Compton进程的CPU占用,如果持续在20%以上,说明特效开销过大; - 用
xrestop看当前X服务器里pixmap数量和内存占用,异常增长说明某窗口在持续重绘(比如conky、各种system monitor); - 必要时用
x11perf测一下当前X服务器的基本渲染能力,作为基线参照。
这些工具在大多数发行版仓库里都有,装一遍不费事。有了基线数据,后面每一项配置改动是变好还是变坏,你心里就有数了。
3. X Render后端的可行优化路径:从开关到重绘策略
3.1 对着配置文件做减法
Compton的配置项核心逻辑是“默认开启的特效太多”。我建议先跑一套最小配置,确认流畅度,再按需开启需要的效果。下面这个配置片段是在X Render后端下直接有效的:
backend = "xrender"; vsync = true; shadow = false; fading = false; no-dock-shadow = true; no-dnd-shadow = true; detect-client-opacity = false; detect-rounded-corners = false; unredir-if-possible = true;逐个说理由:
shadow = false:直接砍掉最吃CPU的卷积模糊。如果桌面有窗口没有阴影感觉太“扁”,可以只保留少数关键窗口的阴影(后面讲排除法);fading = false:关闭窗口映射、取消映射时的淡入淡出动画,避免每次切换窗口带来的连续多帧重绘;no-dock-shadow = true和no-dnd-shadow = true:防止Dock栏和拖放操作触发额外的阴影计算;detect-client-opacity = false:关闭客户端主动上报的透明度检测。有些程序会上报自己的窗口透明度,检测逻辑本身需要轮询,关闭后低端机有明显改善;detect-rounded-corners = false:关闭圆角检测相关逻辑,减少窗口形状变更时对阴影和背景的重算;unredir-if-possible = true:这个选项特别适合全屏视频和游戏场景。它允许Compton在全屏窗口无需合成时暂时卸载合成,直接把窗口内容送往显示器,既能降CPU又能消除撕裂。XRandR下的全屏播放器、浏览器全屏视频基本都是靠这个机制受益的。
3.2 更精准的“区域”优化:让合成器别管不需要的窗口
“一刀切关特效”的办法简单粗暴有效,但有些人就是离不开阴影和透明效果,那我推荐用排除法。Compton支持按窗口属性做精细排除,配置文件里的写法如下:
shadow-exclude = [ "name = 'Notification'", "class_g = 'Conky'", "class_g = 'Docker'", "name = 'firefox'" ];这段的意思是:通知弹窗、conky系统监控、Docker桌面、Firefox窗口不生成阴影。Firefox这种长时间打开、滚动频繁的窗口,阴影的卷积计算量尤其大,排除它对日常流畅度帮助非常明显。
窗口排除还可以用opacity-rule,把某些窗口的透明度设置为接近100%而不走Alpha混合路径:
opacity-rule = [ "99:class_g = 'URxvt'", "98:class_g = 'okular'" ];透明度设成99%和100%在视觉上几乎看不出差别,但合成器可以少做一次不透明窗口的Alpha合并,处理路径更轻松。
需要注意的是,排除规则匹配的窗口类名需要用xprop WM_CLASS查,不同程序的实际类名跟你以为的不一定一样。我遇到过几次规则不生效,最后发现是类名大小写写错了——X11的窗口类名是大小写敏感的。
3.3 重绘与撕裂控制:vsync在xrender下的真实表现
Compton的vsync参数在不同后端下的行为差别很大。在GLX后端下,它可以借助OpenGL的交换间隔来同步垂直刷新;在X Render后端下,实现往往退化为“收到垂直回扫信号后再提交画面”的同步方式。实际效果因Xorg驱动而异:在Intel开源驱动下用vsync = true通常有效,能明显减轻滚动时的撕裂;在部分老NVIDIA驱动下,vsync = true反而会让部分OpenGL程序帧率被拖累。
我在X Render后端上测试时的经验是:
- 先用默认
vsync = true测,如果出现Micro-stutter(细小的周期性卡顿),尝试改成vsync = "none"后对比撕裂程度; - 如果屏幕上半部和下半部分画面错位明显,就保留
true,这比撕裂更影响观感; - 全屏视频场景下,
unredir-if-possible = true往往比强行开vsync更有效,因为全屏视频根本不经过合成路径,再去讨论vsync没有意义。
还有个小技巧:测试撕裂时不要只靠肉眼盯滚动网页,用xrefresh -sync强制整屏刷新一次,仔细观察有没有横向错位的扫描线。用glxgears跑起来后拖动窗口,也能快速暴露vsync没生效的问题。
3.4 实话说:什么场景应该直接换后端,而不是优化X Render
优化X Render后端的前提是它值得优化。如果你的机器显卡支持OpenGL、Xorg驱动也正常,GLX后端在绝大多数情况下都比X Render平滑得多,这是结构决定的,不是靠调参数能翻盘的。我把三种后端的情况列个表,方便你判断:
| 后端 | 兼容性 | 特效性能 | CPU依赖 | 典型适用场景 |
|---|---|---|---|---|
| xrender | 最好,任何Xorg驱动通吃 | 较差,阴影/模糊是软渲染 | 高 | 老机器、GPU无硬件加速、虚拟机、远程X会话 |
| glx | 较好,需要GLX支持 | 好,特效交给GPU | 低 | 正常桌面、NVIDIA闭源驱动、Intel/AMD开源驱动 |
| dri3 | 好,需要Xorg 1.19+ | 较好,但特效支持不完整 | 中 | 较新Linux发行版、AMD/Intel开源驱动 |
X Render后端真正不可替代的场景就三类:没有GPU驱动的机器、VMware/QEMU里没装virtio-gpu、以及通过X11转发跑远程桌面。在这些场景里,后端优化是唯一的选择;如果条件允许换后端,别犹豫,直接换。
4. 实测对比:优化前后的性能和撕裂表现
4.1 我的测试环境
先把测试环境写在前面,方便你换算到自己的机器上。测试机是一台2013年前后的ThinkPad,i5-3320M处理器、HD 4000核显、8GB内存,系统Ubuntu 22.04,Xorg会话,XFCE桌面,Compton版本0.1-beta2(功能上与picom 9.x相近)。屏幕是1366x768,这在今天已经算低分辨率了,但用于测试X Render后端的性能特征反而更有代表性——分辨率越高,软件渲染压力越大,如果你在1080p或2K屏上,开销差距会比我这里看到的更明显。
测试方法上,我固定跑四个场景:
- 空闲桌面:启动后停30秒,记录Compton进程CPU占用;
- 网页滚动:Firefox打开本地长页面连续滚动30秒,记录CPU和主观流畅度;
- 窗口拖动:用xdotool脚本反复移动一个窗口30秒,观察合成器负载变化;
- 全屏视频:mpv播放720p本地视频,观察全屏时是否掉帧。
每个场景跑三遍取平均值,避免我手抖造成的偶然误差。
4.2 场景化测试数据
先看默认配置(什么都不改,仅指定backend = "xrender")的表现:
| 场景 | Compton CPU占用 | 主观感受 |
|---|---|---|
| 空闲桌面 | 14% ~ 22% | 偶尔有轻微迟滞 |
| 网页滚动 | 25% ~ 35% | 滚动掉帧,像隔着一层雾 |
| 窗口拖动 | 30% ~ 45% | 拖影明显,边界模糊 |
| 全屏视频 | 18% ~ 25% | 全屏切换时有半秒黑屏 |
这个CPU占用对于一台老双核四线程机器来说相当可观了,尤其是空闲桌面竟然也占这么多,说明阴影和窗口状态检测在无操作时也在持续消耗。
换成前面第三部分那套最小配置后,同样场景的数据:
| 场景 | Compton CPU占用 | 主观感受 |
|---|---|---|
| 空闲桌面 | 2% ~ 4% | 无感知 |
| 网页滚动 | 6% ~ 10% | 顺滑,无明显掉帧 |
| 窗口拖动 | 8% ~ 12% | 拖影大幅减轻 |
| 全屏视频 | 1% ~ 3% | 全屏切换瞬间完成 |
最直观的变化是空闲和全屏视频场景。空闲场景下降是因为关闭了阴影重绘和透明度检测;全屏视频场景大幅下降则要归功于unredir-if-possible,让全屏窗口绕过了合成路径。
如果只关阴影不关淡入淡出,CPU占用会比上面的数字高一截,大概在10%这一档。我的结论是:在X Render后端下,阴影是最大的敌人,淡入淡出次之。
4.3 最小可复现优化配置(可直接抄作业)
我整理了一份在X Render后端下实测稳的方案,文件名compton.conf,你可以直接放到~/.config/compton/或者~/.config/picom/下(取决于你的发行版):
backend = "xrender"; vsync = true; shadow = false; fading = false; no-dock-shadow = true; no-dnd-shadow = true; detect-client-opacity = false; detect-rounded-corners = false; unredir-if-possible = true; shadow-exclude = [ "name = 'Notification'", "class_g = 'Conky'" ]; opacity-rule = [ "99:class_g = 'URxvt'" ];注意:不同版本的Compton/picom对配置文件选项的命名有细微差异。比如老版本是detect-rounded-corners = false,新版本改成了corner-radius = 0之类;如果你在启动时看到“Unrecognized option”提示,输出compton --help查看本机支持的选项名即可。这种版本差异我在两台不同发行版的机器上就遇到过几次,改配置前先查一下是省时间的做法。
5. 优化落地时的环境排雷笔记
5.1 编译xdotool时遇到xtest.h缺失怎么处理
做重绘压力测试时,我经常会用到xdotool来自动化窗口操作。有一次在一台刚装好系统的Ubuntu 22.04上编译xdotool,跑了make之后直接报错:
xdottool.c:31:10: fatal error: x11/extensions/xtest.h: No such file or directory这个错误本质上跟Compton无关,但xdotool依赖XTest扩展来模拟输入事件,而XTest的C头文件不在X11的核心开发包里面。在Debian/Ubuntu系列上,解决办法是安装额外的开发包:
sudo apt install libxtst-dev libxi-dev装完后再跑一次make,问题就消失了。如果你用的是Fedora、CentOS这类RPM系发行版,对应的包名是libXtst-devel。
装好之后可以用一条命令确认头文件已经就位:
find /usr/include -name "xtest.h"能看到/usr/include/X11/extensions/xtest.h就说明妥了。
我在这里把xdotool的价值延伸一下:做好之后,你可以用循环脚本模拟“持续拖动窗口”的重绘压力,观察Compton的CPU变化,从而非常高效地验证你的配置,比如:
for i in $(seq 1 500); do xdotool search --class "firefox" windowmove 0 0 xdotool search --class "firefox" windowmove 300 200 sleep 0.01 done这是压测工具,不是日常操作,跑的时候最好把窗口放在不碍事的位置。
5.2 Wayland回退X11的操作与验证
这个问题和本文的关联在于:Compton的X Render后端只能在Xorg会话下工作,切到Wayland原生会话后,Compton要么完全无效,要么只能作用于XWayland窗口,状态割裂。很多读者需要优化Compton,前提就是先把系统从Wayland登录切回X11。
Ubuntu 22.04默认使用GDM 3显示管理器,切回X11的官方做法是修改配置文件:
sudo nano /etc/gdm3/custom.conf找到这一行:
#WaylandEnable=false去掉行首的#,保存退出,重启gdm3服务,或者干脆重启电脑:
sudo systemctl restart gdm3如果你不想全局修改,也可以在登录界面点击用户名后,右下角齿轮/图标里选择“Xorg/X11会话”再输密码,只对本次登录生效。
重启后一定要验证当前会话类型,确认是真的切到X11了:
echo $XDG_SESSION_TYPE输出x11就对了。如果你用loginctl这种方式查询,也可以这样:
loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type我在不少机器上遇到过改了custom.conf但进了桌面还是Wayland的情况,常见原因是没有重启完整的显示管理器,或者GDM被NetworkManager等影响了启动顺序。遇到的话,先确认/etc/gdm3/custom.conf改对了,再执行一次sudo systemctl restart gdm3,基本都能解决。
5.3 用WindTerm配置X11转发做远程调试
最后说一个偏远程场景的配置,它跟优化Compton的关系在于:很多时候你要调的是服务器或远程工作站的X11桌面,而不是坐在那台机器前面。
WindTerm是一个跨平台SSH客户端,支持X11转发配置,可以在远程Linux主机上启动图形程序时把它转发到本地。配好了X11转发,你就能在自己的笔记本上打开远程桌面里的一个终端,运行compton --config ... --backend xrender直接观察效果,省事不少。
WindTerm里的配置思路是这样的:
- 本地要有一个X Server程序,Windows下常用VcXsrv,Linux/macOS下就是本机自带的X服务;
- 在WindTerm会话配置里找到SSH相关的转发选项,勾选X11转发(有的版本叫“X11 Forwarding”或“转发X11连接”);
- 用这个会话连接远程主机,WindTerm会自动把远程主机的DISPLAY变量指向本地X Server,你运行图形程序时就能在本地弹窗看到界面。
远程Linux主机侧的基本要求是安装了xauth,并且在sshd_config里开启了X11Forwarding yes。
配置好后,可以先用xclock或者xeyes这种轻量程序验证转发通道是否通。通了再跑Compton就别急着看性能数据了——X11转发的图像传输走的是压缩后的X协议,延迟和带宽都跟本地完全不是一个量级,用它来验证“效果开没开、窗口有没有正常合成”可以,用来测帧率和撕裂就失真了。
说实话,远程调试合成器这件事本身就不轻松,因为X11转发场景下最流畅的配置往往就是最省CPU的配置。你辛辛苦苦在远端把特效全部关掉,可能反而发现转发通道的负载也下来了,这倒也算侧面印证了优化方向是对的。
这轮优化折腾下来,我个人最大的体会是:Compton的X Render后端在命名上像是“默认后端”,但它其实是那种“能用但别乱加特效”的兜底方案。老机器上追求流畅,第一优先级永远是把阴影、淡入淡出这类重效果关掉,用排除法只为少数窗口保留必需的特效;第二优先级才是调整重绘策略和vsync。最后剩下的那点资源富余,才是你在X11传统会话里能享受到的舒适度上限。配置改完跑个两三天,如果没发现异常,基本就可以稳定使用了。