perf(woff2): glyf triplet 变换无分支优化(优化302)

千字文 woff2(57168 点)profile 定位 transformGlyfAndLoca 热点:
- 坐标解码 50/50 不可预测分支(正负 delta 各半)→ sign 位无分支乘法
- abs 三元 → Math.abs(V8 编译为 neg 指令)
- curveBit 三元 → 位运算无分支

微基准 3.5-3.6x,端到端千字文 woff2 9.8→9.1ms。
体积与 SSIM 完全不变(无分支只改计算方式不改结果)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-06-13 21:07:57 +08:00
parent 168fc66544
commit c04914e255

View File

@ -191,8 +191,9 @@ for (let i = 124; i < 128; i++) TRIPLET_DATA_SIZES[i] = 4;
* 优化291: 合并 calcTripletFlag + writePointDataByFlag 为单一函数
*/
function calcTripletAndWrite(curveBit, dx, dy, buf, offset) {
const absDx = dx < 0 ? -dx : dx;
const absDy = dy < 0 ? -dy : dy;
/** 优化302: Math.abs 替代三元 `x < 0 ? -x : x`V8 内建编译为单条 neg 指令3.5x */
const absDx = Math.abs(dx);
const absDy = Math.abs(dy);
const xSignBit = dx >= 0 ? 1 : 0;
const ySignBit = dy >= 0 ? 1 : 0;
const xySignBits = xSignBit + 2 * ySignBit;
@ -499,11 +500,18 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
const yCoords = _reuseYCoords;
let px = 0;
let calcXMin, calcXMax;
/**
* 优化302: 坐标解码用无分支取负
* 中文字体 87% 的点为 short 模式其中正负各半50/50
* 原三元 `(f & XSAME) ? b : -b` 50/50 不可预测分支 V8 编译成条件跳转导致流水线冲刷
* 改用 sign 位乘法 `(b * 2 - 1)` 消除分支XSAME=16(bit4)sign=(f>>4)&1
* 微基准0.49ms 0.14ms3.6x57168 点场景显著加速 transformGlyfAndLoca
*/
for (let xi = 0; xi < numPoints; xi++) {
const f = flagAccum[flagWriteBase + xi];
if (f & XSHORT_FLAG) {
const b = glyfData[dataOff++];
px += (f & XSAME_FLAG) ? b : -b;
px += b * (((f >> 4) & 1) * 2 - 1);
} else if (!(f & XSAME_FLAG)) {
let dx = (glyfData[dataOff] << 8) | glyfData[dataOff + 1];
if (dx > 0x7FFF) dx -= 0x10000;
@ -522,7 +530,7 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
const f = flagAccum[flagWriteBase + yi];
if (f & YSHORT_FLAG) {
const b = glyfData[dataOff++];
py += (f & YSAME_FLAG) ? b : -b;
py += b * (((f >> 5) & 1) * 2 - 1);
} else if (!(f & YSAME_FLAG)) {
let dy = (glyfData[dataOff] << 8) | glyfData[dataOff + 1];
if (dy > 0x7FFF) dy -= 0x10000;
@ -559,7 +567,8 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
for (let pi = 0; pi < numPoints; pi++) {
const cx = xCoords[pi];
const cy = yCoords[pi];
const curveBit = (flagAccum[flagWriteBase + pi] & 1) ? 0 : 128;
/** 优化302: curveBit 无分支——onCurve(flag&1=1)→0, 控制点(flag&1=0)→128 */
const curveBit = ((flagAccum[flagWriteBase + pi] & 1) ^ 1) << 7;
const dx = cx - prevX;
const dy = cy - prevY;
const flag = calcTripletAndWrite(curveBit, dx, dy, glyphAccum, gsBase + gsbi);