给自用博客做一份性能账本

给自用博客做一份性能账本
主题插图 · AI 辅助生成

固定数据集测量云库读取往返,记录一次实际优化的前后耗时与正确性检查。

给自用博客做性能优化,我想先回答一个具体问题:读者打开一篇文章时,服务端究竟要去云数据库取几次数据?先弄清楚这条路,通常比直接更换框架更容易得到可解释的结果。

本篇记录的是这版博客实际完成的一次改动。测试环境为本机 Vinext 开发预览与远程 MySQL,结果用于比较同一条链路的前后变化,不等同于线上生产环境的用户体验评分。

把比较条件固定下来

优化前后都使用同一批 14 条示例内容。每个地址先预热一次,再顺序采样七次,记录中位数和本次采样的第 95 百分位。七次样本很少,因此这里的尾延迟只用来观察这组请求,不能据此宣称稳定的容量上限。

地址改动前中位数优化后中位数
内容 API353ms84ms
首页623ms170ms
文章列表609ms150ms
文章详情631ms166ms
手记详情628ms182ms

这些数字来自逐次采样记录。记录同时保留了中间版本,部分采样会有波动,因此不把单次最低值当作最终结论。后来换成原创内容和新图片的数据版本,需要另做一组测试;不能把不同数据集的结果混在一起,声称所有改善都来自同一处代码修改。

减少读取往返

原来的页面通过几个独立函数分别获取设置、文章和资源。这些函数各自检查初始化状态,还会读取文章附加信息。生成页面元数据时,也需要同样的公共内容。

改动后的读取器把公共设置、已发布文章和资源放进同一个批次,再把附加信息组织成按文章编号查询的 Map。正常情况下,公共快照只需要一次网关批处理。数据库尚未初始化时,才进入初始化与重读流程。公共内容 API 也移除了重复的初始化读取;公开媒体字节直接从对象存储获取,不再为每张图片额外查询云库。

const [settingsRows, entryRows, resourceRows] = await db.batch([
  publicSettingsQuery,
  publishedEntriesQuery,
  orderedResourcesQuery,
])

这是结构示意,真实实现保留了未初始化检查、私密内容过滤与数据库错误处理。少一次网络往返,是一次可以直接观察的收益;少一次错误检查,却可能只是把问题藏起来。

缓存要有清楚的寿命

页面和元数据共享公共读取时,使用的是 React 的请求内缓存。没有增加一个跨请求长期保留正文的全局缓存,因此下一次请求仍然可以看到刚保存的修改或数据库切换结果。

为了检查这一点,回归用例会连续读取两个不同版本的正文,并验证私密条目与所有者信息不会出现在公共快照中。只测“变快了”,却不测“还能看到新内容”,不是一个完整的优化验收。

图片也要进入预算

这一版先保留原始生成图,再构建适合网页的 WebP 派生文件。横版图片提供多个宽度,头像也有独立尺寸。页面需要记录图片的宽高,并按实际显示区域选取资源,避免一开始就下载整张原图。

图片文件变小之后,仍要检查角色细节是否可读、封面有没有错误裁切,以及弱网下页面结构是否稳定。压缩数字与阅读体验,是两份需要一起看的证据。

为下一次修改留下基线

每份性能记录都保存数据条数、正文总字符数、测试环境、原始采样和响应体大小。响应体的离线 gzip 估算也会明确标注,它不是浏览器实际网络传输量。

这次改动没有回答所有性能问题。它给项目留下了一条可重复的路径:找到重复工作,固定比较条件,修改实现,再用相同场景验证正确性与耗时。下一次内容增长时,可以沿着这条路重新测量。

给自用博客做一份性能账本 · LovelyCat · 2026-10-21

个人学习与创作札记 · 设计参考 Yohaku