perf(gsub-reachable): format3 失败路径跳过 contextGids 收集

format3 triggerable=false 是常态(初夏纯标点 280 个 format3 首轮全 false)。
失败时只需找首个不在 reachable 的 gid 记 failGid——此刻 contextGids 收集
无意义:break 前已检查的 gid 都在 reachable(inSubset=reachable.has),
调用方对其 reachable.add 是 no-op。改用 coverageFirstExcludedGid(复用
readCoverageGids 带 cache + 遍历短路)分离失败/成功两遍,失败路径省掉
contextGids.add 调用。仅 triggerable=true(coverage 全在子集、量小)时
第二遍收集 contextGids。

reachable 输出集合逐元素一致(初夏 23/FiraCode 89),全基准 SSIM 不变。
初夏 reach 0.265→0.245ms(-8%)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-24 11:28:34 +08:00
parent 3103dd5db1
commit aeb2622a57

View File

@ -57,6 +57,32 @@ function readCoverageGids(r: OTReader, off: number, cache: CoverageCache): numbe
return gids;
}
/**
* coverage inSubset false gid
*
* format1 list u16 + inSubset
* format2 range gid start..end+ inSubset readCoverageGids
* 280 format3 coverage gid
*
*
* gid -1coverage covCache
* lookup type
*
* @param off coverage
* @param inSubset gid
* @returns gid -1
*/
function coverageFirstExcludedGid(
r: OTReader,
off: number,
cache: CoverageCache,
inSubset: (gid: number) => boolean,
): number {
const gids = readCoverageGids(r, off, cache);
for (const g of gids) if (!inSubset(g)) return g;
return -1;
}
/**
* seedGids GSUB target gid seed
*
@ -339,34 +365,46 @@ function collectChainRefs(
/** format3: coverage + SubstLookupRecords
* coverage backtrack/input/lookahead gid
*
* 315 readCovGidsChecked collectChainRefs
* 280 format3 subtable × 2 = 560 /call
* p triggerable coverage
* gid coverage refs */
* coverage contextGids format3 triggerable=false
* 280 format3 false reachable gid
* failGid contextGids break gid reachable
* inSubset=reachable.has reachable.add no-op
* coverageFirstExcludedGid format2 range
* readCoverageGids + triggerable=true coverage
* readCoverageGids contextGids */
let p = off + 2;
let triggerable = true;
/** 三段 coveragebacktrack/input/lookahead逻辑相同读 count逐 coverage 校验 gid 全在子集 */
/** 第一遍:逐 coverage 找首个不在子集的 gid全在子集则 triggerable 保持 true */
for (let seg = 0; seg < 3 && triggerable; seg++) {
const cnt = r.u16(p);
p += 2;
for (let k = 0; k < cnt; k++) {
const covGids = readCoverageGids(r, off + r.u16(p + k * 2), covCache);
for (const g of covGids) {
if (!inSubset(g)) {
triggerable = false;
/** reachable gid gid reachable
* subtable triggerable=false */
failGid.v = g;
break;
}
contextGids.add(g);
const covOff = off + r.u16(p + k * 2);
const excluded = coverageFirstExcludedGid(r, covOff, covCache, inSubset);
if (excluded >= 0) {
triggerable = false;
/** 记录使其失败的 gid供调用方跨轮跳过该 gid 未进 reachable 前,本 subtable 必定仍 false。 */
failGid.v = excluded;
break;
}
}
p += cnt * 2;
}
if (triggerable) {
const substCount = r.u16(p);
for (let k = 0; k < substCount; k++) refs.add(r.u16(p + 2 + k * 4 + 2));
/** triggerable=true coverage gid contextGids
* coverage gid reachable coverageFirstExcludedGid */
let p2 = off + 2;
for (let seg = 0; seg < 3; seg++) {
const cnt = r.u16(p2);
p2 += 2;
for (let k = 0; k < cnt; k++) {
const covGids = readCoverageGids(r, off + r.u16(p2 + k * 2), covCache);
for (const g of covGids) contextGids.add(g);
}
p2 += cnt * 2;
}
const substCount = r.u16(p2);
for (let k = 0; k < substCount; k++) refs.add(r.u16(p2 + 2 + k * 4 + 2));
/** triggerable=true coverage gid reachablereachable
* refs/contextGids reachable */
return true;