对 GPUI 的批评:notify 就是 zone.js,精确化会摧毁它
来源:blog.zortax.de — 2026-11-05
📋 概述
作者把 Rust 桌面 GUI 框架的状态模型分成五类,并用一个问题筛选它们:当一个值变化时,什么会重跑。GPUI 属于「视图级重跑 + 手写 notify」,egui 是立即模式(整帧重跑),Iced 是 Elm 架构(重跑整个 view 再 diff)。他以 GPUI 为例做了基准:3000 行 live rows、每行一个 cached view,改一个标签要 8.4 ms,且开销随树规模线性增长(每 1000 行约 3 ms);把 rows 写成普通元素则是 92 ms。手写相等性检查能把「写入相同值」从 7.9 ms 降到 0.9 µs——恰好说明这份工作被留给了每个调用点。
🔑 核心要点
- GPUI 的
cx.notify() 只携带实体 id,Rust 的 &mut 上没有写屏障,框架看不出哪个字段变了,于是所有未加 .cached() 的视图都会重绘。
- 作者引 Angular 团队 2023 年对 zone.js 的评价作类比:它「只能在事情可能发生时通知我们」,「这种方案没有扩展性」。
- 想让 GPUI 精确,就得把每个投影做成独立实体:一个实体、一个 Render 实现、一个订阅、一份值拷贝、一个手写 guard 和一个宿主,只为表达「这个标签依赖这个计数」。
- gpui-fast 把 3000 行标签从 8.4 ms 降到 3.4 ms,但那一帧仍要走完整棵树;Zed 自己测得保留式在常规负载上「慢 1-3%」。
- 他的结论是:既然领域已收敛到读追踪,不如从一开始就让组件只跑一次、用闭包做响应式洞——忘记写洞会在第一次更新就露馅,忘记 notify 则取决于别的什么碰巧重绘。
💡 金句
保留讨喜的 API,你得到的就是视图级的更新;要精度,你就失去那套讨喜的 API。
👍 0
👎 0
← 返回 Lobsters 首页