-
Notifications
You must be signed in to change notification settings - Fork 78
Open
Description
Hello,
I've been using this library for creating custom base93 string, but the performance was pretty bad for my 200KB inputs.
So I've tried to optimize it a bit manually, and then used modern AI to further improve it (actually, completely rewrite it for my usecase).
For inspiration, this is what I'm using now, including performance comparison:
/**
* This is a replacement for the 'base-x' library.
* It's been almost fully generated by AI (Sonnet Thinking 3.7).
* Using BigInt and bitwise operations, we achieved:
* Firefox encode: 12530ms vs 4278ms = 2.93x
* Chrome encode: 6649ms vs 2377ms = 2.80x
* Firefox decode: 8364ms vs 5408ms = 1.55x
*/
export class BaseX {
readonly #base = BigInt(this.alphabet.length);
constructor(readonly alphabet: string) {
}
encode(buffer: Uint8Array): string {
if (buffer.length === 0) return '';
// Convert buffer to BigInt efficiently using bitwise operations
let value = 0n;
for (let i = 0; i < buffer.length; i++) {
value = (value << 8n) | BigInt(buffer[i]);
}
// Convert to baseX string efficiently using array
const digits: string[] = [];
if (value === 0n) return this.alphabet[0];
while (value > 0n) {
const remainder = Number(value % this.#base);
digits.push(this.alphabet[remainder]);
value /= this.#base;
}
return digits.reverse().join('');
}
decode(data: string): Uint8Array {
if (data.length === 0) return new Uint8Array(0);
// Convert the baseX string to a BigInt value
let value = 0n;
for (let i = 0; i < data.length; i++) {
const digit = this.alphabet.indexOf(data[i]);
if (digit === -1) {
throw new Error(`Invalid character at position ${i}: ${data[i]}`);
}
value = value * this.#base + BigInt(digit);
}
// If value is 0, return a single-byte buffer with value 0
if (value === 0n) {
return new Uint8Array([0]);
}
// Determine buffer size efficiently by counting bytes
let temp = value;
let byteLength = 0;
while (temp > 0n) {
temp >>= 8n;
byteLength++;
}
// Create buffer and fill it from right to left
const buffer = new Uint8Array(byteLength);
for (let i = byteLength - 1; i >= 0; i--) {
buffer[i] = Number(value & 0xffn);
value >>= 8n;
}
return buffer;
}
}Metadata
Metadata
Assignees
Labels
No labels