From bda73ccea87e97f4d08c5068f2e861b342c49392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=AE=E7=94=9F=EF=BC=88=E5=AD=90=E8=99=9A=EF=BC=89?= <2234839456@qq.com> Date: Sat, 25 Jul 2026 06:41:02 +0800 Subject: [PATCH] =?UTF-8?q?perf(gsub-reachable):=20format3=20=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E5=BF=AB=E5=88=A4=E5=86=85=E8=81=94=E4=B8=BB=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=EF=BC=8C=E7=9C=81=E5=AE=8C=E6=95=B4=20collectChainRef?= =?UTF-8?q?s=20=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 初夏纯标点 280 个 format3 首轮全失败(276 个 backtrack 段为空,失败在 input 段), FiraCode 207 个 format3 中 121 个 backtrack 首 gid 即不在 reachable。原实现每个失败 format3 都要走完整 collectChainRefs(函数调用 + refsReuse/ctxGidsReuse.clear + format3 分支进入 + coverageFirstExcludedGid),是首轮固定开销。 format3 触发需 backtrack/input/lookahead 三段全部 gid 在子集,故任一非空段的首个 coverage 首 gid 不在 reachable 即可判定失败。内联读 format + 依次查三段第一个非空段 首 gid,命中失败则直接记 failGidMap 跳过 collectChainRefs。 字节一致性:5 字体 reachable sha 全 IDENTICAL。 性能 best-of 5000(min):初夏 0.0557→0.0435(-22%)、FiraCode 0.0999→0.0903(-10%)、 霞鹜 -3%、得意黑 -7%、鸿蒙 -8%。快判未命中走完整路径(含 errorFlag 安全网),越界保护 subAbs+6/covOff+6 ≤ byteLength,损坏表降级 collectChainRefs。 Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/font_util/gsub-reachable.ts | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/backend/font_util/gsub-reachable.ts b/backend/font_util/gsub-reachable.ts index a2b1ef3..694c711 100644 --- a/backend/font_util/gsub-reachable.ts +++ b/backend/font_util/gsub-reachable.ts @@ -309,6 +309,50 @@ export function collectReachableGsubTargets( /** 已知失败 gid 仍未进 reachable → 必定仍 triggerable=false,跳过重扫 */ const knownFail = failGidMap.get(subAbs); if (knownFail !== undefined && !reachable.has(knownFail)) continue; + /** format3 失败快判内联(避免大量失败 format3 的完整 collectChainRefs 调用开销): + * 初夏纯标点 280 个 format3 首轮全失败(276 个 backtrack 段为空,失败在 input 段), + * FiraCode 207 个 format3 中 121 个 backtrack 首 gid 即不在 reachable。 + * format3 触发需 backtrack/input/lookahead 三段全部 gid 在子集,故【任一非空段】的首个 coverage + * 首 gid 不在 reachable 即可判定失败。依次查 backtrack→input→lookahead 第一个非空段首 gid, + * 命中失败则记 failGidMap 跳过 collectChainRefs(省函数调用 + clear + format3 分支进入)。 + * 快判未命中(首 gid 在 reachable 或所有段空或 format 非 3)走完整 collectChainRefs(含 errorFlag 安全网)。 */ + { + /** 命中失败时记录的 gid(某段首 gid 不在 reachable),-1 表示快判未命中 */ + let fastFailGid = -1; + /** format3 布局:format(2)+btCnt(2)+btCov[btCnt]+inCnt(2)+inCov[inCnt]+laCnt(2)+laCov[laCnt] */ + if (subAbs + 6 <= dv.byteLength && dv.getUint16(subAbs, false) === 3) { + /** 当前段的 count 字段位置与 count 值,从 backtrack 段开始 */ + let segCntPos = subAbs + 2; + let segCnt = dv.getUint16(subAbs + 2, false); + /** 依次检查 backtrack / input / lookahead 三段,找第一个非空段且首 gid 不在 reachable */ + for (let seg = 0; seg < 3 && fastFailGid < 0; seg++) { + if (segCnt > 0) { + /** 该段首个 coverage offset 紧跟 segCnt 字段 */ + const covOffPos = segCntPos + 2; + if (covOffPos + 2 <= dv.byteLength) { + const covOff = subAbs + dv.getUint16(covOffPos, false); + if (covOff + 6 <= dv.byteLength) { + const covFormat = dv.getUint16(covOff, false); + const covCount = dv.getUint16(covOff + 2, false); + if ((covFormat === 1 || covFormat === 2) && covCount > 0) { + const firstGid = dv.getUint16(covOff + 4, false); + if (!inSubset(firstGid)) fastFailGid = firstGid; + } + } + } + } + /** 推进到下一段:跳过 segCnt 字段 + segCnt 个 coverage offset */ + const nextSegCntPos = segCntPos + 2 + segCnt * 2; + if (nextSegCntPos + 2 > dv.byteLength) break; + segCntPos = nextSegCntPos; + segCnt = dv.getUint16(segCntPos, false); + } + } + if (fastFailGid >= 0) { + failGidMap.set(subAbs, fastFailGid); + continue; + } + } /** type6:收集可触发规则引用的 lookup index 与所需 context gid */ refsReuse.clear(); ctxGidsReuse.clear();