Skip to Content
内部原理局部重排与 damage model

局部重排与 damage model

这一块是 Ansiq runtime 成熟化里最值得警惕的部分之一。

因为很多复杂度都来自这条链:

  • signal 更新
  • dirty scope
  • subtree replacement
  • 哪些祖先必须 relayout
  • 哪些兄弟只是位置变化
  • 哪些 region 需要 redraw
  • 哪些 region 其实不该动

为什么这件事难

它不是一个单独的问题,而是一串连续问题。

一旦边界不清楚,就会出现:

  • 过度 relayout
  • 过度 redraw
  • 终端 patch 太大
  • 看起来“没报错但布局总是怪怪的”

Ansiq 当前的方向

Ansiq 现在已经有:

  • ancestor-chain relayout
  • invalidated region tracking
  • overlapping dirty path normalization
  • 更明确的 layout protocol 和 render math 分层

也就是说,它已经不再是“整树 relayout -> 整块 redraw”的粗模型。

damage model 和 relayout 不是一回事

这是很重要的一条区分:

  • relayout 关心的是几何与位置
  • damage model 关心的是终端哪些区域真的变了

一个节点的位置变化,不代表整块区域都必须重画。

为什么这会持续成为重点

因为越到后期,Ansiq 越不能靠“先整块刷了再说”来掩盖边界问题。

真正成熟的 runtime 一定要把这一层越收越细、越做越可预测。

当前已经收紧到什么程度

目前这条链里已经明确存在:

  • dirty scope 收集
  • dirty path 归一化
  • ancestor-chain relayout
  • invalidated region tracking
  • full redraw 与 partial redraw 的边界

这意味着 Ansiq 已经不再依赖“整树重排、整块重画”去掩盖边界问题。

normalize_dirty_paths(...):先把脏路径压缩干净

如果一个节点和它的子节点同时被标脏,例如:

[0] [0, 0]

本质上只需要按父路径处理一次。

normalize_dirty_paths(...) 这一类逻辑做的就是:

  • 重复路径去重
  • 父路径吞掉已被覆盖的子路径

如果不先做这一步,就会出现:

  • 重复 ancestor relayout
  • 重复 damage 计算
  • 表面上没错,但性能和可解释性都会变差

所以 partial relayout 的成熟化,不只是“少算一些布局”,而是让这条链更可证明。

ancestor-chain relayout:只沿祖先链向上传播

Ansiq 当前并不是“某个节点脏了,就从根重新算一遍”。

更接近的策略是:

  1. 找到 dirty subtree
  2. 用新子树替换旧子树
  3. 沿着它的祖先链向上重新测量和重新定位
  4. 直到几何不再继续变化

这就是 ancestor-chain relayout。

它比“整树 relayout”小得多,但又比“只算当前节点”更正确。因为一个子树尺寸变了,最先受到影响的通常不是它自己,而是:

  • 它的父节点怎么分配空间
  • 它的兄弟节点是否要重新定位
  • 更上层容器的总高度是否变化

为什么 wrapper 高度同步也是这条链的一部分

另一个隐蔽问题是:

  • dirty subtree 已经替换了
  • 包装节点还拿着旧的 measured height

这会让父节点继续按旧高度分配 child rect。看起来像“布局偶尔错位”,实际上是 relayout 边界没收紧。

所以这一层不仅要减少工作量,还要保证:

  • 新子树的几何真正向上传播
  • 只有必须知道这件事的祖先重新计算

damage model 为什么要跟着这条链走

当 ancestor-chain relayout 算出新的 rect 之后,damage model 才能继续回答:

  • 旧 rect 和新 rect 哪些区域必须清掉
  • 哪些区域只是需要重画内容
  • 哪些兄弟虽然没 rerender,但因为位置变化仍然要重画

所以 layout invalidation 和 damage model 不是两套互不相干的优化,而是同一条更新链的前后两段。

这和 patch emission 的关系

最终目标不是漂亮的内部结构,而是更小、更稳定的终端 patch:

  • relayout 太大,patch 一定也会变大
  • damage model 太粗,终端残影和多余 redraw 更容易出现

所以这部分虽然是 internals 主题,但它会直接影响:

  • 交互稳定性
  • 终端残影
  • 长时间运行时的性能

下一步

继续阅读:

  1. 终端 session 与 viewport
  2. Viewport 与历史
  3. 历史与 scrollback
Last updated on