From ff0a91422a2fed4764e3f96eabf7be0ef049a88b Mon Sep 17 00:00:00 2001 From: JoostK Date: Sun, 8 Dec 2019 20:37:45 +0100 Subject: [PATCH] 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 --- packages/compiler/src/i18n/digest.ts | 53 +++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/packages/compiler/src/i18n/digest.ts b/packages/compiler/src/i18n/digest.ts index eec617a81b..e81a26e6a1 100644 --- a/packages/compiler/src/i18n/digest.ts +++ b/packages/compiler/src/i18n/digest.ts @@ -110,13 +110,13 @@ export function sha1(str: string): string { const len = utf8.length * 8; 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 + 64 >> 9) << 4) + 15] = len; 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++) { 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); } - 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); - [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, b, c, d, e] = [add32(a, h0), add32(b, h1), add32(c, h2), add32(d, h3), add32(e, h4)]; + a = add32(a, h0); + b = add32(b, h1); + c = add32(c, h2); + d = add32(d, h3); + e = add32(e, h4); } 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] { 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)) { hi = hi ^ 0x130f9bef; @@ -174,18 +184,21 @@ export function fingerprint(str: string): [number, number] { } export function computeMsgId(msg: string, meaning: string = ''): string { - let [hi, lo] = fingerprint(msg); + let msgFingerprint = fingerprint(msg); if (meaning) { - const [him, lom] = fingerprint(meaning); - [hi, lo] = add64(rol64([hi, lo], 1), [him, lom]); + const meaningFingerprint = fingerprint(meaning); + msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint); } + const hi = msgFingerprint[0]; + const lo = msgFingerprint[1]; + return byteStringToDecString(words32ToByteString([hi & 0x7fffffff, lo])); } function hash32(str: string, c: number): number { - let [a, b] = [0x9e3779b9, 0x9e3779b9]; + let a = 0x9e3779b9, b = 0x9e3779b9; let i: number; const len = str.length; @@ -194,7 +207,8 @@ function hash32(str: string, c: number): number { a = add32(a, wordAt(str, i, Endian.Little)); b = add32(b, wordAt(str, i + 4, 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)); @@ -203,11 +217,11 @@ function hash32(str: string, c: number): number { c = add32(c, len); 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 -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; b = sub32(b, c); b = sub32(b, a); b ^= a << 8; 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)]; } -function add64([ah, al]: [number, number], [bh, bl]: [number, number]): [number, number] { - const [carry, l] = add32to64(al, bl); +function add64(a: [number, number], b: [number, number]): [number, number] { + 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); return [h, l]; } @@ -256,7 +274,8 @@ function rol32(a: number, count: number): number { } // 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 l = (lo << count) | (hi >>> (32 - count)); return [h, l];