perf(gsub-reachable): format3 失败 gid 跨轮跳过冗余扫描

不动点迭代中 format3 triggerable=false 的 subtable,记录使其失败的第一个
coverage gid。下一轮若该 gid 仍未进 reachable,本 subtable 必定仍 false,
直接跳过 collectChainRefs 重扫。

原 settledChain 只记忆稳定 subtable(format2 / format3 triggerable=true),
format3 triggerable=false 每轮都重扫。初夏纯标点 280 个 format3 全 false,
3 轮 × 280 = 840 次 collectChainRefs;改后 chainCalls 280→(第 2 轮起全跳过),
-67%。失败 gid 进 reachable 时重扫(可能仍 false 则更新失败 gid,可能变 true
则转 settledChain)。

reachable 集合字节级一致(初夏/得意黑/思源全 cmp 通过),SSIM 全程不变。
初夏 reach 0.33→0.29ms(-13%,collectChainRefs 非 reach 全部开销故收益有限)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-24 11:05:52 +08:00
parent 65e238cdca
commit 8c311768f6

View File

@ -136,6 +136,15 @@ export function collectReachableGsubTargets(
* reachable 使 coverage gid
*/
const settledChain: Set<number> = new Set<number>();
/**
* format3 gid format3 triggerable=false subtable使
* coverage gid gid reachable subtable false
* 280 format3 false 3 × 280 = 840 collectChainRefs 2
* gid reachable false gid true settledChain
*/
const failGidMap: Map<number, number> = new Map<number, number>();
/** 复用对象,避免每次调用 collectChainRefs 分配 */
const failGidBox: { v: number } = { v: -1 };
while (changed) {
changed = false;
@ -144,10 +153,14 @@ export function collectReachableGsubTargets(
for (const subAbs of lk.subtableAbsOffs) {
if (lk.effectiveType === LT_CHAIN) {
if (settledChain.has(subAbs)) continue;
/** 已知失败 gid 仍未进 reachable → 必定仍 triggerable=false跳过重扫 */
const knownFail = failGidMap.get(subAbs);
if (knownFail !== undefined && !reachable.has(knownFail)) continue;
/** type6收集可触发规则引用的 lookup index 与所需 context gid */
refsReuse.clear();
ctxGidsReuse.clear();
const stable = collectChainRefs(r, subAbs, refsReuse, ctxGidsReuse, inSubset, covCache);
failGidBox.v = -1;
const stable = collectChainRefs(r, subAbs, refsReuse, ctxGidsReuse, inSubset, covCache, failGidBox);
for (const g of ctxGidsReuse) {
if (!reachable.has(g)) { reachable.add(g); changed = true; }
}
@ -161,7 +174,13 @@ export function collectReachableGsubTargets(
}
}
}
if (stable) settledChain.add(subAbs);
if (stable) {
settledChain.add(subAbs);
failGidMap.delete(subAbs);
} else if (failGidBox.v >= 0) {
/** triggerable=false记录失败 gid下轮据此跳过 */
failGidMap.set(subAbs, failGidBox.v);
}
} else {
const newTargets = collectSubtableTargets(r, subAbs, lk.effectiveType, inSubset, covCache);
for (const g of newTargets) {
@ -274,6 +293,8 @@ function collectChainRefs(
contextGids: Set<number>,
inSubset: (gid: number) => boolean,
covCache: CoverageCache,
/** out: triggerable=false 时记录第一个不在 reachable 的 coverage gid跨轮跳过判定用 */
failGid: { v: number },
): boolean {
const format = r.u16(off);
if (format === 1) {
@ -333,6 +354,9 @@ function collectChainRefs(
for (const g of covGids) {
if (!inSubset(g)) {
triggerable = false;
/** reachable gid gid reachable
* subtable triggerable=false */
failGid.v = g;
break;
}
contextGids.add(g);