性能实测

以下均为单机实测值(未做系统化基准测试),用于量级参考而非承诺。

兼容性矩阵(133 样例,脚本可复现)

对 133 份真实 OFD 样例(examples/resources/*.ofd 65 份 + corpus/ofd/*.ofd 68 份:数科电子发票、 发票监制章、非标命名空间、国标原文、OFD R&W 测试集等)逐份执行七项功能。下表数字由脚本实测产出, 不是手写值,任何一次重建后都能复现:

node scripts/compat-matrix.mjs --cli target/release/ofd-cli.exe
# → eval-out/compat-report.json(显式样例清单 + 字节数 + sha256、逐样例结论、CLI 指纹)
功能 通过率 说明
info(元信息) 132/133 唯一失败 sanitized_vat_invoice.ofd(OFD.xml 空根负向样例)
list(包内文件) 132/133 同上
render(渲染 ≤12 页) 131/133 累计 346 张 PNG;失败 = 负向样例 + sample0.ofd(0×0 页面按 0.17 起中文报错)
verify(原签名校验) 132/133 唯一失败同负向样例
sign + verify(签名回环) 132/133 唯一失败同负向样例;2026-10-12 修复后复跑(见下)
encrypt + decrypt(加密回环) 133/133 容器级回环,不需要文档可解析
decrypt 语义一致 131/131(2 N/A) 页数与包内文件列表与原文一致;字节不同(解密重写 ZIP 容器,属预期)

口径与偏差说明:

  • 2 份负向样例(examples/resources/sample-hidden.ofd:Page/@ID 非正整数; sanitized_vat_invoice.ofd:DocBody 缺 DocRoot)是给解析器当反例的损坏包, 判据是「exit≠0 且给出明确结构错误、不 panic」,不是「能解析」;第 7 项对它们无比较基线,记 N/A;
  • verify 对原始签名的结论分布:有效 23、无签名 89、未提供信任公钥无法判定 12、 摘要不符 6。测试集里本就含刻意篡改的文件,「签名无效」是正确结论而非失败;
  • 已修复项(2026-10-12):sign + verify 曾 7/132 未过——sign 写入 Doc_N/Signs/Signatures.xml 后未更新 OFD.xml/Document.xml 引用的那份签名列表, 且 body_matches_dir 只认 Doc_0/... 前缀(漏 /Doc_0/Document.xml 与目录形式 Doc_0), 导致「sign 报成功、verify 看不到新签名」。现按「写进被引用的那份列表;无引用才新建并回填」 修复(引用已存在时逐字节不改 OFD.xml,避免破坏把它纳入保护范围的既有签名), 133 份样例签名回环已 132/133(唯一失败为负向样例);历史失败原因仍保留在报告 JSON 的 perSample[].items.signVerify;
  • 旧文「73 份样例 × 七项全部通过 / 165 张 PNG」是 2026-09-16 的一次性数据 (见 docs/article/README.md),当时未落清单与报告,已由本表替换;
  • CLI 指纹(字节数/mtime/sha256)随报告一起落盘,便于判断矩阵对应哪次构建。

网页 vs 原生:逐像素一致性

examples/node-demo/parity-check.mjs:WASM 渲染与原生 CLI 渲染的 PNG 逐像素比对。

最近一次 结果
6 个样例 6/6 差异 0.000%

这是「同一渲染内核」架构的直接证据——不是「看起来一样」,是字节级一样。

WASM 资源体积

资源 原始 gzip -9 后
ofd_wasm_bg.wasm(渲染内核,0.24.0,含 JPX/JPEG2000 渲染解码、CMS/CRL/时间戳验签与 GBK XML 兼容) 3.84 MiB 1.40 MiB
中文回退字体(思源宋体 GB2312 子集 TTF,站点自备) 2.96 MiB 1.77 MiB

另有转换模块(0.24.0 5.05 MiB / gzip 1.91 MiB,含 JPEG2000 原生解码、裸 Type 1 字体转换与 GBK XML 兼容)与工具模块(2.94 MiB / gzip 1.09 MiB,含表单填写、手写墨迹注释、OFD 加解密、OFD-A 修复与签名验证),按需懒加载。渲染内核自 v0.10.0 起 vendor openjpeg 支持渲染方向 JPX 图像;不需要时可在构建侧关闭 ofd-render 的 jpx feature 减小体积。

口径:packages/ofd/.gen 三模块产物 + examples/vue-demo/public/fallback-font.ttf; 数字可由 node scripts/ci-check.mjs 复现(2026-10-23 重建后实测;gzip -9 为本机 node zlib,与 OS gzip 结果略有差异)。重建 wasm 后此表须同步更新,勿沿用旧值。

部署建议:为 .wasm/.ttf 开启 gzip/brotli 预压缩(gzip_static/brotli_static),带 hash 的静态资源配置长缓存(immutable,wasm 固定文件名的缓存配套);回退字体懒加载(首次打开文件时)。在线阅读器实现加载全过程的逐块进度可视化。

OFD-A 合规率(2026-10-23 实测)

模式(valid=130) 修复前 修复后 10 项全通过 字体嵌入通过
系统字体精确匹配 0 130(100%) 130(100%)
--fallback-font 显式替代 0 130(100%) 130(100%)

口径与剩余字体清单见 标准与合规;复现 node scripts/ofda-compliance.mjs --cli target/release/ofd-cli.exe --fallback-font examples/resources/fallback-font.ttf(产出 JSON/CSV/报告)。合规率依赖运行环境已安装的字体;缺字体时报告 font-missing,不会静默替换。

转换耗时

样本 页数 原生 CLI 浏览器 WASM
GB/T 42133-2022 国标原文 14 0.47s ~1s

首次加载

演示站首次访问需下载渲染内核 + 回退字体(合计约 6.8 MiB 原始 / 约 3.2 MiB gzip),二次访问命中浏览器缓存即瞬时可用。慢网络下的体验:所有大资源下载均有进度条与资源名提示(用户明确要求的核心体验)。