1.8 KiB
1.8 KiB
第七章:如何避免长文本拖垮算法
7.1 一次调用的成本也取决于字符串长度
假设为了知道单词的每个位置能否断开,依次测量:
a
ab
abc
abcd
……
虽然只调用了 n 次 Canvas,总共提交的字符量却是:
1 + 2 + … + n = n(n + 1) / 2
因此只数 API 调用次数还不够,也要数测量请求总共处理了多少文字。
7.2 96 个字素的边界
measurement.ts 的 getSegmentFit()按引擎与输入情况使用字素求和、相邻组合、前缀等测量模型。
前缀测量限定在 MAX_PREFIX_FIT_GRAPHEMES = 96 以内。超过这一规模,相关路径改用相邻字素组合,限制提交给 Canvas 的文字量随长度增长的放大程度。
这并不等于严格证明浏览器内部 shaping 总是线性的。它限制的是库自己构造测量请求所造成的成本;浏览器字体引擎还有自己的工作。
7.3 逐行继续时,不从头重扫
逐行 API 将上一行结束的游标传给下一行,遍历从那里继续。若每取下一行都从全文开头重新定位,行数多时会累积出大量重复工作。
RESEARCH.md 的 Keeping Work Bounded记录了许多实际陷阱,包括增长字符串的反复处理、从每行起点重扫到文本结尾、重复搜索断行片段。阅读性能代码时,除了看一次循环的内容,也要问:这个循环会被重复启动多少次?
本章检查:每个前缀只测一次,能否保证总成本是 O(n)?不能,因为每次测量的输入长度在增长。