From 23b36a9fbc40223585e5477acb628199d86a495e Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Thu, 8 Feb 2024 09:42:46 +0100 Subject: [PATCH] perf: simpler & faster base32 encode (#40) * perf: simpler & faster base32 encode This is mainly a PoC, similar room for optimization in other encodings * includePadding statement * udd changeset --------- Co-authored-by: pilcrowOnPaper --- .changesets/r9sme.patch.md | 1 + src/encoding/base32.ts | 29 +++++++++++------------------ 2 files changed, 12 insertions(+), 18 deletions(-) create mode 100644 .changesets/r9sme.patch.md diff --git a/.changesets/r9sme.patch.md b/.changesets/r9sme.patch.md new file mode 100644 index 0000000..088dd33 --- /dev/null +++ b/.changesets/r9sme.patch.md @@ -0,0 +1 @@ +Improve `base32.encode()` performance. \ No newline at end of file diff --git a/src/encoding/base32.ts b/src/encoding/base32.ts index 7604c56..ec2daca 100644 --- a/src/encoding/base32.ts +++ b/src/encoding/base32.ts @@ -33,29 +33,22 @@ export class Base32Encoding implements Encoding { } ): string { let result = ""; - const chunkCount = Math.ceil(data.length / 5); - for (let i = 0; i < chunkCount; i++) { - let buffer1 = data[i * 5]! << 24; - buffer1 += (data[i * 5 + 1] ?? 0) << 16; - buffer1 += (data[i * 5 + 2] ?? 0) << 8; - buffer1 += data[i * 5 + 3] ?? 0; - for (let j = 0; j < 6; j++) { - const key = (buffer1 >> (27 - 5 * j)) & 0x1f; - result += this.alphabet[key]; + let block = 0; + let shift = 0; + for (let i = 0; i < data.length; i++) { + block = (block << 8) | data[i]!; + shift += 8; + while (shift >= 5) { + shift -= 5; + result += this.alphabet[(block >> shift) & 0x1f]; } - const buffer2 = data[i * 5 + 4] ?? 0; - let key = ((buffer1 & 0x03) << 3) + (buffer2 >> 5); - result += this.alphabet[key]; - key = buffer2 & 0x1f; - result += this.alphabet[key]; } - let padCount = 0; - if (data.length % 5 !== 0) { - padCount = 8 - Math.ceil(((data.length % 5) * 8) / 5); + if (shift > 0) { + result += this.alphabet[(block << (5 - shift)) & 0x1f]; } - result = result.slice(0, result.length - padCount); const includePadding = options?.includePadding ?? true; if (includePadding) { + const padCount = (8 - (result.length % 8)) % 8; for (let i = 0; i < padCount; i++) { result += "="; }