From 9af42218d2c7abed97066f826b46c548065f2f3c Mon Sep 17 00:00:00 2001 From: Sergei Russkikh Date: Fri, 31 Mar 2023 15:07:40 -0700 Subject: [PATCH 1/2] Introducing late Uint8Array initialization This is the fix for the latency issue when the initialization code is executed once it is loaded into runtime and causes an increase in parsing & execution time regardless of its usage. In particular, Uint8Array buffer initialization either triggers GC sweep or blocks a network thread in older browsers (ArrayBuffers used to be allocated from the network heap). --- lib/utils/strings.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/utils/strings.js b/lib/utils/strings.js index c8f097cd..03e53743 100644 --- a/lib/utils/strings.js +++ b/lib/utils/strings.js @@ -15,12 +15,14 @@ try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APP // Table with utf8 lengths (calculated by first byte of sequence) // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, // because max possible codepoint is 0x10ffff -const _utf8len = new Uint8Array(256); -for (let q = 0; q < 256; q++) { - _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); +let _utf8len = null; +function maybeInitializeUtf8LenBuffer() { + _utf8len = new Uint8Array(256); + for (let q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); + } + _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start } -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - // convert string to array (typed, when possible) module.exports.string2buf = (str) => { @@ -113,6 +115,7 @@ module.exports.buf2string = (buf, max) => { // NB: by unknown reasons, Array is significantly faster for // String.fromCharCode.apply than Uint16Array. const utf16buf = new Array(len * 2); + maybeInitializeUtf8LenBuffer(); for (out = 0, i = 0; i < len;) { let c = buf[i++]; @@ -169,6 +172,8 @@ module.exports.utf8border = (buf, max) => { // If we came to start of buffer - that means buffer is too small, // return max too. if (pos === 0) { return max; } + + maybeInitializeUtf8LenBuffer(); return (pos + _utf8len[buf[pos]] > max) ? pos : max; }; From 4867557890c8fc57f4f778576df2f3d2ac0812e8 Mon Sep 17 00:00:00 2001 From: Sergei Russkikh Date: Fri, 31 Mar 2023 15:21:25 -0700 Subject: [PATCH 2/2] Adding missing if statement Adding missing if statement to initialize Uint8Array only once --- lib/utils/strings.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/utils/strings.js b/lib/utils/strings.js index 03e53743..d0e07980 100644 --- a/lib/utils/strings.js +++ b/lib/utils/strings.js @@ -17,11 +17,13 @@ try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APP // because max possible codepoint is 0x10ffff let _utf8len = null; function maybeInitializeUtf8LenBuffer() { - _utf8len = new Uint8Array(256); - for (let q = 0; q < 256; q++) { - _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); + if (_utf8len === null) { + _utf8len = new Uint8Array(256); + for (let q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); + } + _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start } - _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start } // convert string to array (typed, when possible)