Skip to content

Conversation

Chanran
Copy link

@Chanran Chanran commented Sep 29, 2025

Same to dankogai/js-base64#186, it might have performance issue like js-base64 when use atob or btob polyfill. So I create pr to optimize it.

Copy link
Owner

@zloirock zloirock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should use unbound versions of methods like this. After that, please, check performance and show results since unbound methods will cause some slowdown.

Copy link

@Rudxain Rudxain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're at optimizations, would pre-allocating like output = Array.from({ length: string.length * 3/4 }) improve perf?

@Chanran
Copy link
Author

Chanran commented Oct 11, 2025

  • use origin 3.44.0 core-js-pure/actual/atob
image image

10ms+minor_gc.json

  • use optimized code by changing 3.44.0 node_modules/core-js-pure/modules/web.atob.js:
image image

1ms_minor_gc.json

  • test demo

core-js-atob-demo 2.zip

  1. npm i
  2. npm start
  3. copy big_base64_data.txt content to textarea
  4. change "Decode Count" to 1000
  5. open devtools performance panel and record
  6. click "Decode" button

@Chanran
Copy link
Author

Chanran commented Oct 11, 2025

@zloirock @Rudxain The performance problem is that every character "+=" in earch loop will new a string and drop it. That will lead to minor gc much time.

@Chanran Chanran requested a review from zloirock October 11, 2025 03:30
@Rudxain
Copy link

Rudxain commented Oct 11, 2025

every character "+=" in each loop will new a string and drop it

I understand. What I meant is that an engine/runtime might not infer how much memory needs to be allocated for the output array (I'm talking about your patch, not the old code). So by creating an array with the expected number of elements (and replacing push by indexed-assignment), the engine won't have to realloc

@Chanran
Copy link
Author

Chanran commented Oct 11, 2025

But I tested when changing to Array.from or var arrayFrom = require('./internals/array-from'), performance will even worse than "[]" in chrome.
image

@Chanran Chanran force-pushed the lcr/feat-optimize-atob-btoa-performance branch from f32fc31 to 9be5d63 Compare October 11, 2025 08:41
@zloirock
Copy link
Owner

Array.from({ length }) is the worst thing you can do for performance - look at how many observable operations there are by specification. Also, it's a very heavy dependency. You could use Array constructor with length argument. Sure, it should be cached too.

@Chanran
Copy link
Author

Chanran commented Oct 11, 2025

  • use Array constructor and use outputIndex to accelerate
var output = Array(Math.ceil(string.length * 3 / 4));
var outputIndex = 0;
while (position < length) {
    chr = charAt(string, position++);
    bs = bc % 4 ? bs * 64 + c2i[chr] : c2i[chr];
    if (bc++ % 4) output[outputIndex++] = fromCharCode(255 & bs >> (-2 * bc & 6));
}
return output.join('');
image
  • use []
image

@Chanran
Copy link
Author

Chanran commented Oct 15, 2025

@zloirock Can the pr be merged?

@zloirock
Copy link
Owner

zloirock commented Oct 15, 2025

@Chanran you haven't fixed that was requested.

Also, please, create array with Array constructor with length and don't forget cache it locally too (var $Array = Array;).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants