-
Notifications
You must be signed in to change notification settings - Fork 593
[Bug] #183
Description
感谢你向 ClashX 提交 issue!
在提交之前,请确认:
- 我已经在 ……/ 中找过我要提出的问题
- 这是 ClashX UI层面的问题,并非 Clash Core 的问题(例如xx软件连不上,无法连接特定服务器等)。其他 Clash 衍生版本没有次问题。
- 如果你可以自己 debug 并解决的话,提交 PR 吧!
我都确认过了,我要继续提交。
clashX config
selectOutBoundMode = rule
selectConfigName = "clash_meta"
showNetSpeedIndicator = 0
restoreTunProxy = 1
restoreSystemProxy = 0
ClashX log
与代理核心通信正常,无异常日志输出。
高 CPU 占用不伴随日志错误,为 UI 层渲染循环问题。
ClashX Crash log
无崩溃。进程正常运行但持续高 CPU 占用。
环境 Environment
- 使用者的操作系统:macOS 26.4 (Build 25E246, Apple Silicon ARM64)
- ClashX Meta 版本:v1.4.31 (640)
- 网络环境:家庭网络,正常使用
- ISP:无 DNS 污染
- 其他:问题在 macOS 26 上出现,此前在旧版 macOS 上未出现
说明 Description
ClashX Meta 主进程(非 Clash Core)在 macOS 26.4 上持续占用约 50% CPU。通过 sample 采样分析,几乎 100% 的 CPU 时间消耗在
NSStatusItem(菜单栏图标)的重绘上,而非代理核心的网络处理。
核心问题:macOS 26 的私有框架 UpdateCycle(UC::DriverCore::continueProcessing())在每次 RunLoop 迭代都触发 Core Animation
事务提交,导致 ClashX 的 NSStatusBarButtonCell 每秒被重绘数百次。
此外,退出 ClashX 主程序后,以 root 权限运行的 com.metacubex.ClashX.ProxyConfigHelper(PID
43717)未被正常终止,因主程序消失导致连接断开后进入重试死循环,CPU 飙升至约 200%。
重现问题的具体步骤 Steps to Reproduce
- 在 macOS 26.4 上启动 ClashX Meta v1.4.31
- 正常使用代理功能,无需任何特殊操作
- 观察 Activity Monitor 中 ClashX Meta 进程的 CPU 占用
我预期会发生……?
ClashX Meta 正常运行时 CPU 占用应较低(通常 < 5%),菜单栏图标仅在有状态变化时更新。
实际上发生了什麽?
- ClashX Meta 主进程 CPU 持续占用 ~50%,通过 sample 工具分析,3 秒内采集 2143 个样本(~714 次/秒),几乎全部消耗在
NSStatusBarButtonCell drawWithFrame:inView: → NSViewBackingLayer display 的重绘循环中 - 即使关闭「显示网速」选项(showNetSpeedIndicator = 0),问题依然存在
- sample 调用链显示:UC::DriverCore::continueProcessing() (UpdateCycle) → CA::Transaction::commit() →
CA::Layer::display_if_needed() → NSViewBackingLayer display → NSStatusBarButtonCell drawWithFrame:inView: - 3 秒内 NSStatusBarButtonCell 重绘 191 次,NSViewBackingLayer display 369 次
- 退出 ClashX 后,ProxyConfigHelper 残留进程 CPU 占用 ~200%
可能的解决方案 Possible Solution
- NSStatusItem 渲染优化:macOS 26 引入了 Scene-based status
item(NSSceneStatusItem、NSStatusItemScene),渲染管线发生变更。建议在每次 RunLoop 事务提交时检查 NSStatusItem
内容是否实际发生了变化,避免无意义的重绘。可参考 Apple 对 NSStatusItem 在 macOS 26 中的变更说明 - 降级 Core Animation 事务刷新频率:当前 UC::DriverCore 驱动的事务在每个 RunLoop
迭代都触发,可考虑对状态栏图标的更新做节流(throttle),例如限制到每秒最多 1-2 次 - ProxyConfigHelper 生命周期管理:主程序退出时应主动向 ProxyConfigHelper 发送终止信号,而非依赖 helper
自行检测主程序状态,避免因连接断开导致的重试死循环
更多信息 More Information
sample 分析完整调用链(关键部分):
Call graph:
2143 Thread_738305: Main Thread
+ 2143 NSApplicationMain
+ 2143 -[NSApplication run]
+ 2143 RunCurrentEventLoopInMode
+ 2136 _CFRunLoopRunSpecificWithOptions
+ 686 __CFRunLoopDoSource1
+ 686 UC::DriverCore::continueProcessing() (in UpdateCycle)
+ 682 stepTransactionFlush
+ 681 CA::Transaction::flush_as_runloop_observer
+ 631 CA::Transaction::commit()
+ 530 CA::Context::commit_transaction
+ 524 CA::Layer::display_if_needed
+ 369 -[NSViewBackingLayer display]
+ 338 -[NSViewBackingLayer drawInContext:]
+ 328 -[NSView _recursive:displayRectIgnoringOpacity:inContext:]
+ 239 -[NSControl drawRect:]
+ 191 -[NSStatusBarButtonCell drawWithFrame:inView:]
+ 188 -[NSSystemStatusBar drawBackgroundInRect:inView:]
+ 188 -[NSSceneStatusItem _setSelectedContentFrame:options:]
+ 188 -[NSStatusItemScene updateSettings:transition:]
活跃维护的替代客户端(如 ClashVerge Rev、Clash Nyanpasu 等)因使用 Tauri/Web 技术栈渲染 UI,不依赖 macOS 原生
NSStatusItem,不受此问题影响。