Skip to content

Commit 1b1c84f

Browse files
committed
feat: optimize atobPolyfill performance to avoid minor gc
1 parent df91b05 commit 1b1c84f

File tree

3 files changed

+34
-15
lines changed

3 files changed

+34
-15
lines changed

base64.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,24 @@
197197
if (!b64re.test(asc))
198198
throw new TypeError('malformed base64.');
199199
asc += '=='.slice(2 - (asc.length & 3));
200-
var u24, bin = '', r1, r2;
200+
var u24, r1, r2;
201+
var binArray = []; // use array to avoid minor gc in loop
201202
for (var i = 0; i < asc.length;) {
202203
u24 = b64tab[asc.charAt(i++)] << 18
203204
| b64tab[asc.charAt(i++)] << 12
204205
| (r1 = b64tab[asc.charAt(i++)]) << 6
205206
| (r2 = b64tab[asc.charAt(i++)]);
206-
bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
207-
: r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
208-
: _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
207+
if (r1 === 64) {
208+
binArray.push(_fromCC(u24 >> 16 & 255));
209+
}
210+
else if (r2 === 64) {
211+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255));
212+
}
213+
else {
214+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255));
215+
}
209216
}
210-
return bin;
217+
return binArray.join('');
211218
};
212219
/**
213220
* does what `window.atob` of web browsers do.

base64.mjs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,24 @@ const atobPolyfill = (asc) => {
163163
if (!b64re.test(asc))
164164
throw new TypeError('malformed base64.');
165165
asc += '=='.slice(2 - (asc.length & 3));
166-
let u24, bin = '', r1, r2;
166+
let u24, r1, r2;
167+
let binArray = []; // use array to avoid minor gc in loop
167168
for (let i = 0; i < asc.length;) {
168169
u24 = b64tab[asc.charAt(i++)] << 18
169170
| b64tab[asc.charAt(i++)] << 12
170171
| (r1 = b64tab[asc.charAt(i++)]) << 6
171172
| (r2 = b64tab[asc.charAt(i++)]);
172-
bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
173-
: r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
174-
: _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
173+
if (r1 === 64) {
174+
binArray.push(_fromCC(u24 >> 16 & 255));
175+
}
176+
else if (r2 === 64) {
177+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255));
178+
}
179+
else {
180+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255));
181+
}
175182
}
176-
return bin;
183+
return binArray.join('');
177184
};
178185
/**
179186
* does what `window.atob` of web browsers do.

base64.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,22 @@ const atobPolyfill = (asc: string) => {
169169
asc = asc.replace(/\s+/g, '');
170170
if (!b64re.test(asc)) throw new TypeError('malformed base64.');
171171
asc += '=='.slice(2 - (asc.length & 3));
172-
let u24, bin = '', r1, r2;
172+
let u24, r1, r2;
173+
let binArray: string[] = []; // use array to avoid minor gc in loop
173174
for (let i = 0; i < asc.length;) {
174175
u24 = b64tab[asc.charAt(i++)] << 18
175176
| b64tab[asc.charAt(i++)] << 12
176177
| (r1 = b64tab[asc.charAt(i++)]) << 6
177178
| (r2 = b64tab[asc.charAt(i++)]);
178-
bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
179-
: r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
180-
: _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
179+
if (r1 === 64) {
180+
binArray.push(_fromCC(u24 >> 16 & 255));
181+
} else if (r2 === 64) {
182+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255));
183+
} else {
184+
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255));
185+
}
181186
}
182-
return bin;
187+
return binArray.join('');
183188
};
184189
/**
185190
* does what `window.atob` of web browsers do.

0 commit comments

Comments
 (0)