4.2 KiB
第十章:亲自验证性能机制
10.1 先把问题变成可观察的证据
本教程关心四件事:
- 首次准备是否调用 Canvas?
- 相同文本再次准备是否复用测量?
- 改变宽度做布局时是否继续调用 Canvas?
- 这些样本的预测高度是否与 DOM 相符?
下载脚本后,将它放进研究版本的 Pretext 仓库 tutorials/zh-CN/verify.cjs(按需新建目录),因为它以该位置查找 ../../src。
随文的 verify.cjs用真实 Chromium Canvas,在 measureText() 外包一层计数器,同时统计提交字符串的 UTF-16 码元总数。然后测试英文、中文、保留空白的文本。
实验不使用伪造的平均字宽。源码通过 Node 的 TypeScript 转换功能转换为浏览器模块;没有修改库实现。
10.2 第一次研究保存的结果
原始记录在 results.chrome156.json。环境为本机 macOS、Headless Chrome 156、DPR 1,设置 <html lang="en">,使用记录脚本中的命名字体及其回退链。三段文本都重复了 12 次,刻意让缓存效果可观察。
| 样本 | 字符串 length | 首次 Canvas 次数 | 首次提交码元数 | 再次准备 Canvas 次数 | 变宽布局 Canvas 次数 |
|---|---|---|---|---|---|
| 英文 | 1,428 | 62 | 529 | 0 | 0 |
| 中文 | 408 | 53 | 67 | 0 | 0 |
| 保留空白、tab、软连字符 | 888 | 50 | 497 | 0 | 0 |
每段分别在 80、121、200、319、320、321、480、800px 下求高度,24 组结果与 DOM 高度一致。这只能证明这些样本的高度一致,不能证明所有语言与断行位置都完全一致。
10.3 怎样理解计时数据
预先准备后,每轮做 3,000 次宽度切换,热身后取 5 轮中位数。原始记录为:
| 样本 | Pretext 布局总时间 | DOM 改宽后立即测高总时间 |
|---|---|---|
| 英文 | 1.7ms | 86.0ms |
| 中文 | 1.5ms | 57.8ms |
| 保留空白等 | 6.3ms | 93.9ms |
这些数字展示“用已测宽度计算”与“改变 DOM 宽度后同步求几何信息”的成本差异。它们不包含 Pretext 首次准备成本,也不包含完整页面绘制。
这不是严谨的产品性能排名:样本很少且重复,固定先测 Pretext 再测 DOM,没有记录硬件与电源条件,短样本受计时分辨率影响,也没有与批量 DOM 测量对照。结果不应被宣传成“任意页面快几十倍”。更可靠的机制证据是调用次数和这组样本的结果核对。
10.4 复现方法
要求 Node 23.10+ 或支持 module.stripTypeScriptTypes(..., { mode: 'transform' }) 的较新 Node、Playwright,以及可用 Chromium。
为避免改动本仓库的依赖,在单独目录安装实验依赖:
mkdir -p /tmp/pretext-study-deps
npm install --prefix /tmp/pretext-study-deps playwright
/tmp/pretext-study-deps/node_modules/.bin/playwright install chromium
在本仓库根目录运行:
PLAYWRIGHT_MODULE=/tmp/pretext-study-deps/node_modules/playwright \
node tutorials/zh-CN/verify.cjs
默认打印 JSON,不覆盖已归档结果。若要保存本次输出:
PLAYWRIGHT_MODULE=/tmp/pretext-study-deps/node_modules/playwright \
node tutorials/zh-CN/verify.cjs --output /tmp/pretext-study-result.json
也可以通过 CHROME_EXECUTABLE 指定已安装 Chrome 的可执行文件路径;两种方式选一种即可。脚本只监听本机回环地址,结束后关闭服务器与浏览器。
脚本会检查 24 组高度、重复准备和布局的 Canvas 调用次数,以及行文本 API 与行数 API 的行数一致性。失败时返回非零状态。它不设置速度阈值,因为这种微型计时不适合承担性能回归门禁。
项目正式验证还要看 harness/README.md 与 harness/bench/README.md:区分新文本、已见文本、resize、生成行文本与最坏情况;同时处理浏览器自身缓存、JIT、GC 和跨轮噪声。本教程没有运行完整的固定浏览器 harness,也没有把 headless 结果当成其正式准确性基线。