代理客户端怎么选?从 Clash、Shadowrocket 的延迟实测说起

同一个代理节点,换个客户端,会不会更快?

这次在 Mac 上测试了 Shadowrocket 和 Clash by Hako。通过近端 VLESS + TLS 服务完成一次新建连接请求,默认条件下,Shadowrocket 的中位耗时约为 53.4 ms,Clash 约为 4.7 ms。连接复用后,两者相对直连的额外耗时中位数都不到 0.2 ms。

差距主要出现在第一次请求。进一步抓包发现,Shadowrocket 的连接中出现了约 40 ms 的 TCP 确认等待;调整服务端 ACK 行为后,其新建连接耗时降到了约 6.5 ms。

如果你关心的是连接刚建立时的响应速度,这次测试中,Clash by Hako 的表现更好。 下面先看两款客户端的差异,再追踪这几十毫秒去了哪里。

目录

首次请求:53.4 ms 与 4.7 ms

为了减少公网线路波动的干扰,我们把代理服务和 HTTP 目标放在同一台 Mac 内的 Linux 虚拟机上。测试程序通过客户端的本地 HTTP CONNECT 入口,经 VLESS + TLS 访问目标,读取完整响应后停止计时。

新建连接的耗时包含连接建立、适用的握手和一次 HTTP 请求。服务端保持默认 ACK 行为时,结果如下,单位均为毫秒(ms):

客户端新建连接中位数新建连接 P95
Shadowrocket53.36458.344
Clash by Hako4.6677.279

两款客户端分批测试,没有进行同时段交错的双客户端对测;各批次均设置直连和 Python VLESS 对照,完整基线列在后面的测试方法中。P95 表示约 95% 的样本不超过的耗时。

53.4 ms 是一次请求的完整耗时。 Shadowrocket 同批次的直连中位数为 1.683 ms,Clash 同批次为 0.714 ms。两批基线有所变化,但 Shadowrocket 的几十毫秒等待也在复测中重复出现:首次为 53.484 ms,复测为 53.364 ms。

当一次操作需要新建连接,尤其存在连续、相互依赖的请求时,这类等待更值得关注。它是否会带来明显体感,还取决于应用如何建立和复用连接。

连接复用后,两者开销都很小

连接已经建立后,在同一条通道上继续发送请求,默认 ACK 条件下的结果是:

客户端复用连接中位数复用连接 P95相对直连的额外耗时中位数
Shadowrocket0.5510.7410.192
Clash by Hako0.3330.5010.113

最后一列先计算每轮客户端请求与直连请求的耗时差,再取中位数,因此不一定等于两个中位数直接相减。

两款客户端复用连接后的额外开销都在毫秒以下。本次最显著的差异集中在首次请求;只看连接复用后的成绩,会漏掉这段等待。

Shadowrocket 的约 40 ms 等在了哪里?

首次拆分 Shadowrocket 的连接过程时,建立 CONNECT 通道约需 6–8 ms,随后第一次 HTTP 请求又等待了约 43–48 ms。

抓包中的一条连接出现了这样的时序:

时间事件
15:25:15.110254客户端向服务端发送 64 字节数据
15:25:15.153325服务端发送 ACK,确认收到数据
15:25:15.153461客户端随即发送下一段数据

服务端约 43 ms 后才确认收到数据,客户端收到确认后紧接着发送后续数据。另一条连接也出现了约 40 ms 的间隔,符合 TCP 小包发送与 delayed ACK(延迟确认)相互等待的特征。

我们只对虚拟机返回 Mac 的测试路径临时启用 QUICKACK,让服务端更及时地确认数据,然后重新测量:

客户端默认 ACK:新建中位数QUICKACK:新建中位数QUICKACK:新建 P95
Shadowrocket53.3646.5028.484
Clash by Hako4.6674.4646.564

Shadowrocket 从约 53.4 ms 降到 6.5 ms,Clash 则从约 4.7 ms 变为 4.5 ms。Shadowrocket 首轮测量也出现了同样变化:53.484 → 6.751 ms。在这套环境里,Shadowrocket 的首次请求明显受到 ACK 等待影响,Clash 没有出现同样量级的延迟。

这些证据支持 TCP 确认等待的解释;没有客户端内部追踪,还无法确定具体是哪一处实现触发了这种交互。但对使用者而言,这几十毫秒仍然是等待请求完成时实际付出的时间。

QUICKACK 改变了服务端的 TCP 行为,这组数据用于解释原因。前面的默认结果更直接地反映了此次未作调整时的表现。

这次怎么选,接下来测什么

如果主要看本次 macOS、VLESS + TLS 环境下的首次请求延迟,我会更倾向于 Clash by Hako:默认条件下,新建连接请求约需 4.7 ms,Shadowrocket 则约需 53.4 ms。即使调整服务端 ACK 行为,Shadowrocket 降到约 6.5 ms 后,Clash 在本次测量中仍然更快一些。

连接复用后,两者相对直连的额外耗时中位数都不到 0.2 ms。对大量复用已有连接的应用,这次测得的差距就小得多。

这次测试的 Clash by Hako 使用 mihomo 1.19.31 内核。它在新建连接上的表现,可能得益于 mihomo 的连接处理实现。接下来会继续补测其他客户端和内核,也会比较采用相同内核的不同客户端,看看这种优势能否重复出现。

测试环境与方法

以下是供核对和复测使用的环境、基线与本机测试数据。

项目配置
测试日期2026 年 10 月 2 日
设备与系统Apple M3,macOS 14.8.9
Shadowrocket2.2.92(3445),本地 HTTP 入口 127.0.0.1:1082
Clash by Hako1.0.12(57),mihomo 1.19.31,本地 HTTP 入口 127.0.0.1:7890
服务端Mac 内的 Linux 虚拟机 192.168.1.4
Docker 服务Xray 26.3.27、Python HTTP 服务,使用 host 网络
代理协议VLESS TCP + TLS,临时自签名证书,仅测试节点允许不验证该证书
HTTP 目标HTTP/1.1,固定返回 2 字节 ok
未启用REALITY、Vision、mux

文中的 Clash 指表中这款应用及内核版本。测量范围是 macOS 上的本地 HTTP/CONNECT 入口和近端 VLESS 路径,尚未覆盖公网、iPhone、TUN 数据路径、UDP 或大流量;目标请求也不涉及 DNS 和目标站的 HTTPS 握手。

计时使用 perf_counter_ns(),从建立连接或发出请求开始,到读取完整响应结束。新建连接计入建连时间;复用连接沿用已经建立的 TCP 通道。服务端日志确认请求经过 VLESS,直连对照的路由没有进入 TUN。近端 HTTP 服务和 Python VLESS 对照 socket 启用了 TCP_NODELAY。

本机每条路径测 300 次新建连接、500 次复用请求,另各预热 20 次;VLESS 每条路径测 100 次新建连接、200 次复用请求,另各预热 10 次。同一批次内各路径随机交错,默认 ACK 与 QUICKACK 分开统计。首次本机 Shadowrocket 测试只保留了统计输出,后续各批次保留逐次样本。

VLESS 各批次的完整结果

下表采用 Shadowrocket 最后一次复测和 Clash 正式测试。Python 最小 VLESS 实现用来帮助定位路径差异。

条件批次与路径新建中位数新建 P95复用中位数复用 P95
默认 ACKShadowrocket 批次:直连1.6833.0370.3680.474
默认 ACKShadowrocket53.36458.3440.5510.741
默认 ACK同批 Python VLESS10.69814.1790.4350.644
默认 ACKClash 批次:直连0.7141.0530.2200.354
默认 ACKClash4.6677.2790.3330.501
默认 ACK同批 Python VLESS6.6688.4020.2760.406
QUICKACKShadowrocket 批次:直连0.7081.0280.2480.366
QUICKACKShadowrocket6.5028.4840.3860.549
QUICKACK同批 Python VLESS6.5008.2620.2990.423
QUICKACKClash 批次:直连0.6821.0280.1990.328
QUICKACKClash4.4646.5640.3120.472
QUICKACK同批 Python VLESS6.5997.8250.2430.387

QUICKACK 条件下,按每轮与直连配对计算,新建/复用连接的额外耗时中位数分别为 Shadowrocket 5.642 / 0.138 ms、Clash 3.731 / 0.100 ms。这些差值包含协议握手、服务端处理和两端调度等整条路径上的额外耗时。

本机 CONNECT 转发

这组目标位于 Mac 回环地址,经过客户端的本地代理入口,没有经过 VLESS 节点。

批次与路径新建连接中位数复用连接中位数
Shadowrocket 批次:本机直连0.1900.083
Shadowrocket:CONNECT0.5070.141
Clash 批次:本机直连0.1890.086
Clash:CONNECT0.3510.131

分别与本批次直连中位数相减,Shadowrocket 增加约 0.317 / 0.058 ms,Clash 增加约 0.162 / 0.045 ms。两款客户端在这组本机转发中的额外开销都在毫秒以下。