文档再长,输入也不会变慢的理由
写短笔记时,任何编辑器都很快。差别会在文档变长时显现,而这种差别取决于按下一个键的成本是随编辑范围增长,还是随文档大小增长。

短笔记用任何编辑器写都很快。差别会在文档变长时显现。
如果每次按键都重新读取整篇文档并重新布局画面,那么文档越长,输入也会越慢。这就是在十行笔记中表现良好的编辑器,到了两千行的设计文档中却让人感到卡顿的原因。
mote 没有把这个问题视为以后再解决的性能问题,而是从一开始就将其定为必须遵守的设计原则。
编辑时,只重新读取和布局发生变化的范围。只有打开文件时才重新读取整篇文档。
只重新读取发生变化的地方
在 Markdown 中,前面的行可能会改变后面行的含义。如果在文档上方开启代码块,下面的所有内容都可能变成代码;同一句话位于列表或引用块中时,也会被以不同方式解读。
因此,mote 会记住前文影响确定结束的“安全点”。发生编辑后,它会从附近的安全点开始读取,并在内容重新稳定的瞬间停止。
后面的块不会重新读取。如果行数增加或减少,就只移动它们的位置。这样,成本随实际发生变化的范围增长,而不是随整篇文档增长。
解析器遵循 CommonMark 的逐行算法,并通过了全部 652 项规范测试。但增量处理很容易悄无声息地出错。因此,我们会对随机文档应用 3,600 次随机编辑,并在每次编辑后,将结果与重新读取整篇文档得到的结果进行比较。
这项检查也发现了真实的错误。那是安全点与被编辑的行恰好重合的情况。
用检查来守住性能原则
目标是从按下按键到核心处理结束,p95 不超过 4ms。一旦超过这个时间,就不会将其视为改进事项,而是作为错误处理。
我们也没有只把规则写在文档里。自动检查会确认完整重新解析是否只在打开文件时使用。它还会阻止空闲状态下反复运行的定时器或帧任务。
性能也不由人凭肉眼判断。测试工具会在真实画面中输入按键,并测量处理时间的分布。我们关注的不是平均值或中位数,而是 p95。因为让用户感到卡顿的,并不是平时的速度,而是偶尔出现的长时间延迟。
测量始终使用同一份固定文档。

doc100k.md 的画面。状态栏显示 96,513 个字符和 103 分钟的阅读时间。画面也只更新必要的部分
只将解析器改成增量处理还不够。
代码块的语法高亮在每次编辑时都会重新处理所有块。这是最后一项无论编辑范围多大,都会随着文档变长而变慢的工作。
现在,未修改块的语法高亮会直接复用。编辑位置之后的块,只会根据行数的变化移动位置。
屏幕之外的块不会进行布局。因为只有同时缩小重新读取和重新绘制的范围,才能在长文档中维持速度。
也有例外
有时必须重新处理整篇文档。
比如打开文件或换行格式发生变化时。修改链接引用定义后,文档中任何位置的链接都可能发生变化,因此画面更新范围也会扩大到整篇文档。
即使核心很快,画面仍然需要时间等待下一帧。对于 60Hz 的屏幕,帧间隔本身就会成为极限。因此,我们会分别测量核心处理时间和内容实际出现在屏幕上所需的时间,不会把这两个数字放在同一条轴线上。这就是封面上的两条数据不同的原因。
快速的编辑器,并不是把所有事情都做得很快的编辑器。
而是不做那些没有必要做的事情的编辑器。