perf(woff2): triplet 编码无分支 abs + 符号位提取

transformGlyfAndLoca 的 y+triplet 循环每点原先 4 次三元判断(absDx/absDy/xSign/ySign),
中文字体 dx/dy 正负近似 50/50 为不可预测分支,致流水线冲刷。

改用 Int32 算术右移统一提取符号:
- dxSgn = dx >> 31(0 或 -1)
- absDx = (dx ^ dxSgn) - dxSgn(无分支 abs)
- xSignBit = dxSgn + 1(等价 dx >= 0 ? 1 : 0)

令东 74.6% 点走 case3,收益最大:woff2 端到端 2.197→2.078ms(-5.4%),
思源 0.662→0.653ms(-1.4%)。sha256 字节级一致,全基准 SSIM 零变化。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
崮生(子虚) 2026-07-24 12:08:48 +08:00
parent 60db8d226b
commit bcd4574b3f

View File

@ -507,20 +507,32 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
const curveBit = ((f & 1) ^ 1) << 7;
const dx = cx - prevX;
const dy = cy - prevY;
const absDx = dx < 0 ? -dx : dx;
const absDy = dy < 0 ? -dy : dy;
/**
* 优化317: 无分支 abs + 符号位提取
* dx/dy SmIInt32 路径dx >> 31 在非负时为 0负时为 -1算术右移
* absDx = (dx ^ sgn) - sgn sgn=0 时不变sgn=-1 dx^(-1)=~dx~dx-(-1)=~dx+1=-dx
* xSignBit = sgn + 1 01/-10与原 `dx >= 0 ? 1 : 0` 等价
* 中文字体 dx/dy 正负近似 50/50原三元是不可预测分支致流水线冲刷位运算无分支
* 每点消除 4 次三元absDx/absDy/xSign/ySign令东 74.6% 点走 case3 收益最大
*/
const dxSgn = dx >> 31;
const dySgn = dy >> 31;
const absDx = (dx ^ dxSgn) - dxSgn;
const absDy = (dy ^ dySgn) - dySgn;
const xSignBit = dxSgn + 1;
const ySignBit = dySgn + 1;
const wpos = gsBase + gsbi;
let flag;
/** 优化313: 各分支内直接累加 gsbi字节数由分支确定1/1/1/2/3/4消除 TRIPLET_DATA_SIZES 查表 */
let adv;
if (dx === 0 && absDy < 1280) {
_gs[wpos] = absDy & 0xFF;
flag = curveBit + ((absDy & 0xF00) >> 7) + (dy >= 0 ? 1 : 0);
flag = curveBit + ((absDy & 0xF00) >> 7) + ySignBit;
adv = 1;
} else if (dy === 0 && absDx < 1280) {
/** 优化316: case2 去掉冗余 `dx !== 0`——case1 已排除 dx===0走到此分支 dx 必非 0 */
_gs[wpos] = absDx & 0xFF;
flag = curveBit + 10 + ((absDx & 0xF00) >> 7) + (dx >= 0 ? 1 : 0);
flag = curveBit + 10 + ((absDx & 0xF00) >> 7) + xSignBit;
adv = 1;
} else if (absDx < 65 && absDy < 65) {
/** 316: case3 `dx !== 0 && dy !== 0`case1/case2 0
@ -528,8 +540,6 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
const ax = absDx - 1;
const ay = absDy - 1;
_gs[wpos] = ((ax & 0xF) << 4) | (ay & 0xF);
const xSignBit = dx >= 0 ? 1 : 0;
const ySignBit = dy >= 0 ? 1 : 0;
flag = curveBit + 20 + (ax & 0x30) + ((ay & 0x30) >> 2) + xSignBit + 2 * ySignBit;
adv = 1;
} else if (absDx < 769 && absDy < 769) {
@ -538,16 +548,12 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
const ay = absDy - 1;
_gs[wpos] = ax & 0xFF;
_gs[wpos + 1] = ay & 0xFF;
const xSignBit = dx >= 0 ? 1 : 0;
const ySignBit = dy >= 0 ? 1 : 0;
flag = curveBit + 84 + 12 * ((ax & 0x300) >> 8) + ((ay & 0x300) >> 6) + xSignBit + 2 * ySignBit;
adv = 2;
} else if (absDx < 4096 && absDy < 4096) {
_gs[wpos] = absDx >> 4;
_gs[wpos + 1] = ((absDx & 0xF) << 4) | (absDy >> 8);
_gs[wpos + 2] = absDy & 0xFF;
const xSignBit = dx >= 0 ? 1 : 0;
const ySignBit = dy >= 0 ? 1 : 0;
flag = curveBit + 120 + xSignBit + 2 * ySignBit;
adv = 3;
} else {
@ -555,8 +561,6 @@ function transformGlyfAndLoca(glyfData, locaData, indexFormat, numGlyphs) {
_gs[wpos + 1] = absDx & 0xFF;
_gs[wpos + 2] = (absDy >> 8) & 0xFF;
_gs[wpos + 3] = absDy & 0xFF;
const xSignBit = dx >= 0 ? 1 : 0;
const ySignBit = dy >= 0 ? 1 : 0;
flag = curveBit + 124 + xSignBit + 2 * ySignBit;
adv = 4;
}