perf(compiler): speed up i18n digest computations (#34332)
Avoids the usage of array destructuring, as it introduces calls to a `__values` helper function in ES5 that has a relatively high performance impact. This shaves off roughly 130ms of CPU time for a large compilation with big templates that uses i18n. PR Close #34332
This commit is contained in:
parent
014a7137f4
commit
ff0a91422a
|
@ -110,13 +110,13 @@ export function sha1(str: string): string {
|
||||||
const len = utf8.length * 8;
|
const len = utf8.length * 8;
|
||||||
|
|
||||||
const w = newArray(80);
|
const w = newArray(80);
|
||||||
let [a, b, c, d, e]: number[] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
|
let a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476, e = 0xc3d2e1f0;
|
||||||
|
|
||||||
words32[len >> 5] |= 0x80 << (24 - len % 32);
|
words32[len >> 5] |= 0x80 << (24 - len % 32);
|
||||||
words32[((len + 64 >> 9) << 4) + 15] = len;
|
words32[((len + 64 >> 9) << 4) + 15] = len;
|
||||||
|
|
||||||
for (let i = 0; i < words32.length; i += 16) {
|
for (let i = 0; i < words32.length; i += 16) {
|
||||||
const [h0, h1, h2, h3, h4]: number[] = [a, b, c, d, e];
|
const h0 = a, h1 = b, h2 = c, h3 = d, h4 = e;
|
||||||
|
|
||||||
for (let j = 0; j < 80; j++) {
|
for (let j = 0; j < 80; j++) {
|
||||||
if (j < 16) {
|
if (j < 16) {
|
||||||
|
@ -125,12 +125,21 @@ export function sha1(str: string): string {
|
||||||
w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
|
w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [f, k] = fk(j, b, c, d);
|
const fkVal = fk(j, b, c, d);
|
||||||
|
const f = fkVal[0];
|
||||||
|
const k = fkVal[1];
|
||||||
const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
|
const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
|
||||||
[e, d, c, b, a] = [d, c, rol32(b, 30), a, temp];
|
e = d;
|
||||||
|
d = c;
|
||||||
|
c = rol32(b, 30);
|
||||||
|
b = a;
|
||||||
|
a = temp;
|
||||||
}
|
}
|
||||||
|
a = add32(a, h0);
|
||||||
[a, b, c, d, e] = [add32(a, h0), add32(b, h1), add32(c, h2), add32(d, h3), add32(e, h4)];
|
b = add32(b, h1);
|
||||||
|
c = add32(c, h2);
|
||||||
|
d = add32(d, h3);
|
||||||
|
e = add32(e, h4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
|
return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
|
||||||
|
@ -163,7 +172,8 @@ function fk(index: number, b: number, c: number, d: number): [number, number] {
|
||||||
export function fingerprint(str: string): [number, number] {
|
export function fingerprint(str: string): [number, number] {
|
||||||
const utf8 = utf8Encode(str);
|
const utf8 = utf8Encode(str);
|
||||||
|
|
||||||
let [hi, lo] = [hash32(utf8, 0), hash32(utf8, 102072)];
|
let hi = hash32(utf8, 0);
|
||||||
|
let lo = hash32(utf8, 102072);
|
||||||
|
|
||||||
if (hi == 0 && (lo == 0 || lo == 1)) {
|
if (hi == 0 && (lo == 0 || lo == 1)) {
|
||||||
hi = hi ^ 0x130f9bef;
|
hi = hi ^ 0x130f9bef;
|
||||||
|
@ -174,18 +184,21 @@ export function fingerprint(str: string): [number, number] {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computeMsgId(msg: string, meaning: string = ''): string {
|
export function computeMsgId(msg: string, meaning: string = ''): string {
|
||||||
let [hi, lo] = fingerprint(msg);
|
let msgFingerprint = fingerprint(msg);
|
||||||
|
|
||||||
if (meaning) {
|
if (meaning) {
|
||||||
const [him, lom] = fingerprint(meaning);
|
const meaningFingerprint = fingerprint(meaning);
|
||||||
[hi, lo] = add64(rol64([hi, lo], 1), [him, lom]);
|
msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hi = msgFingerprint[0];
|
||||||
|
const lo = msgFingerprint[1];
|
||||||
|
|
||||||
return byteStringToDecString(words32ToByteString([hi & 0x7fffffff, lo]));
|
return byteStringToDecString(words32ToByteString([hi & 0x7fffffff, lo]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function hash32(str: string, c: number): number {
|
function hash32(str: string, c: number): number {
|
||||||
let [a, b] = [0x9e3779b9, 0x9e3779b9];
|
let a = 0x9e3779b9, b = 0x9e3779b9;
|
||||||
let i: number;
|
let i: number;
|
||||||
|
|
||||||
const len = str.length;
|
const len = str.length;
|
||||||
|
@ -194,7 +207,8 @@ function hash32(str: string, c: number): number {
|
||||||
a = add32(a, wordAt(str, i, Endian.Little));
|
a = add32(a, wordAt(str, i, Endian.Little));
|
||||||
b = add32(b, wordAt(str, i + 4, Endian.Little));
|
b = add32(b, wordAt(str, i + 4, Endian.Little));
|
||||||
c = add32(c, wordAt(str, i + 8, Endian.Little));
|
c = add32(c, wordAt(str, i + 8, Endian.Little));
|
||||||
[a, b, c] = mix([a, b, c]);
|
const res = mix(a, b, c);
|
||||||
|
a = res[0], b = res[1], c = res[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
a = add32(a, wordAt(str, i, Endian.Little));
|
a = add32(a, wordAt(str, i, Endian.Little));
|
||||||
|
@ -203,11 +217,11 @@ function hash32(str: string, c: number): number {
|
||||||
c = add32(c, len);
|
c = add32(c, len);
|
||||||
c = add32(c, wordAt(str, i + 8, Endian.Little) << 8);
|
c = add32(c, wordAt(str, i + 8, Endian.Little) << 8);
|
||||||
|
|
||||||
return mix([a, b, c])[2];
|
return mix(a, b, c)[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
function mix([a, b, c]: [number, number, number]): [number, number, number] {
|
function mix(a: number, b: number, c: number): [number, number, number] {
|
||||||
a = sub32(a, b); a = sub32(a, c); a ^= c >>> 13;
|
a = sub32(a, b); a = sub32(a, c); a ^= c >>> 13;
|
||||||
b = sub32(b, c); b = sub32(b, a); b ^= a << 8;
|
b = sub32(b, c); b = sub32(b, a); b ^= a << 8;
|
||||||
c = sub32(c, a); c = sub32(c, b); c ^= b >>> 13;
|
c = sub32(c, a); c = sub32(c, b); c ^= b >>> 13;
|
||||||
|
@ -238,8 +252,12 @@ function add32to64(a: number, b: number): [number, number] {
|
||||||
return [high >>> 16, (high << 16) | (low & 0xffff)];
|
return [high >>> 16, (high << 16) | (low & 0xffff)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function add64([ah, al]: [number, number], [bh, bl]: [number, number]): [number, number] {
|
function add64(a: [number, number], b: [number, number]): [number, number] {
|
||||||
const [carry, l] = add32to64(al, bl);
|
const ah = a[0], al = a[1];
|
||||||
|
const bh = b[0], bl = b[1];
|
||||||
|
const result = add32to64(al, bl);
|
||||||
|
const carry = result[0];
|
||||||
|
const l = result[1];
|
||||||
const h = add32(add32(ah, bh), carry);
|
const h = add32(add32(ah, bh), carry);
|
||||||
return [h, l];
|
return [h, l];
|
||||||
}
|
}
|
||||||
|
@ -256,7 +274,8 @@ function rol32(a: number, count: number): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate a 64b number left `count` position
|
// Rotate a 64b number left `count` position
|
||||||
function rol64([hi, lo]: [number, number], count: number): [number, number] {
|
function rol64(num: [number, number], count: number): [number, number] {
|
||||||
|
const hi = num[0], lo = num[1];
|
||||||
const h = (hi << count) | (lo >>> (32 - count));
|
const h = (hi << count) | (lo >>> (32 - count));
|
||||||
const l = (lo << count) | (hi >>> (32 - count));
|
const l = (lo << count) | (hi >>> (32 - count));
|
||||||
return [h, l];
|
return [h, l];
|
||||||
|
|
Loading…
Reference in New Issue