2026-10-31 XIV DB 数据驱动 SSG 实践评估 (OpenCode, GPT-6.1 Sol)
目标与输入
用真实国服 Item.csv 构建完整物品目录,不把 Notist 的性能问题改成客户端加载详情来回避。
消费者:
/home/azurice/Files/_ffxiv/xiv-db。上游:
thewakingsands/ffxiv-datamining-cn,commit2c6741cffe3cfe70f093c54c463791364e515d8d。输入 SHA-256:
abb68a057f68e4d9d37eae76d31354555d30f76a88554d0d1c04315598c7268f。客户端版本:
2026.10.06.0000.0000;非零 ID 且名称非空的物品 51,225 件。prepare 命令扩展在内存生成
.not文档和模板数据,每件物品一个稳定 HTML 路径,每 100 件生成一页目录。搜索索引是额外的静态资源;关闭 JavaScript 不影响目录翻页和详情正文。
三个性能问题及处理
1. 每页复制整站上下文
notist-ssg/src/build.rs 原来在每页循环中使用 json! 构造含完整 site 的上下文,再调用 Handlebars render 重新序列化。site 包含整站 pages、directories 和 data,因此生成页面越多,重复工作越多。
改为一次建立 handlebars::Context,通过 render_with_context 渲染;逐页替换 page、assets,仅在目录变化时替换 directory。整站查询语义保持不变,新增回归测试检查兄弟页、不同目录、lookup、@root 和资源路径。
单轮本地 release 对照(简单合成页面、无 partial,不代表完整业务负载):
页面数 | 原实现 | 上下文复用后 |
|---|---|---|
100 | 0.063 s | 0.011 s |
300 | 0.507 s | 0.032 s |
600 | 1.936 s | 0.069 s |
600 页产物的全部文件 SHA-256 与原实现一致。临时测量记录位于 /tmp/opencode/notist-catalog-bench-o596atvh/,不是持久化基准设施。
2. 每插入一个发布文件都扫描所有旧路径
publication::Assets::generated 原先用全表遍历检查相同、祖先和后代路径冲突。这会使数万资源的发布规划出现平方级开销。
保留冲突检查,改用已有 BTreeMap:检查路径祖先是否已存在,再查询有序范围中的首个潜在后代。新增双向祖先冲突、相同路径及相似字符串但不同路径组件的测试。
3. Handlebars 隐式 partial 复制当前上下文
即使前两处修复,真实模板中的 {{> head}}、header 和 footer 仍会让 Handlebars 深拷贝整站上下文。检查本机依赖 6.4.4 的 partial.rs 可见其通过 merge_json 构造 partial 的 base value;6.4.1 也有该行为。
这次没有 vendoring、修改依赖缓存或实现特殊的文本内联。站点模板采用 Handlebars 正式支持的显式上下文:{{> head page}},在 partial 中通过 @root.site.title 读取整站信息。这个依赖库边界已写入 SSG 文档;隐式 partial 的通用性能问题并未因此从 Handlebars 本身消失。
全量结果与限制
本机 release 单轮完整构建(含 Python prepare 扩展及输出文件写入,不含首次编译和 CSV 下载):
51,739 张 HTML:51,225 详情 + 513 目录 + 1 首页。
用时 6.974 s。
Linux 子进程
ru_maxrss为 2,622,936 KiB,约 2.50 GiB;不是进程树内存总和。HTML 合计 112,544,774 bytes,搜索索引 1,745,218 bytes。
全量检查详情与分页数量,并解析所有 HTML 验证本地 href/src 存在。
未完成的性能工作:
内存仍偏高,尚未做详细分配剖析;构建保留文档、环境、模板上下文和全部输出,不能据此宣称流式或增量构建。
template 自身的全站遍历仍可能产生平方级开销。
显式传入大型对象的 partial 仍会复制该对象。
命令扩展协议整体传递文档和数据;此轮未修改其协议或增加生成静态资源 API。搜索索引由显式数据准备阶段产生。
当前数据只有物品基本字段,没有图标图片、分类中文名和获取来源;不能声称是完整物品获取途径库。
验证与复现
# Notist 根目录
TERM=dumb NO_COLOR=1
# xiv-db 根目录
CLI 测试在当前 TERM=xterm-256color 环境中有两项既有的重定向输出不含 ANSI 转义断言失败;设置 TERM=dumb NO_COLOR=1 后 CLI 测试全部通过,本次未改颜色处理逻辑。
XIV DB 的 Nix 沙箱构建通过显式本地输入 override 验证,不将本地路径写入依赖锁:
修复尚未提交或发布,消费者默认锁定仍是远端旧版;发布 Notist 修复后应更新消费者 flake.lock,再验证不带 override 的构建。