豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

feat: optimize atob and btoa performance#1464

Closed
Chanran wants to merge 3 commits intozloirock:masterfrom
Chanran:lcr/feat-optimize-atob-btoa-performance
Closed

feat: optimize atob and btoa performance#1464
Chanran wants to merge 3 commits intozloirock:masterfrom
Chanran:lcr/feat-optimize-atob-btoa-performance

Conversation

@Chanran
Copy link
Copy Markdown
Contributor

@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
Copy Markdown
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
Copy Markdown

@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
Copy Markdown
Contributor 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
Copy Markdown
Contributor 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
Copy Markdown

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
Copy Markdown
Contributor 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
Copy Markdown
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
Copy Markdown
Contributor 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
Copy Markdown
Contributor Author

Chanran commented Oct 15, 2025

@zloirock Can the pr be merged?

@zloirock
Copy link
Copy Markdown
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;).

@zloirock
Copy link
Copy Markdown
Owner

@Chanran ?

@johnzhou721
Copy link
Copy Markdown
Contributor

FWIW -- I'd be interested in picking this up if the original author is not available. It'd be a good exercise for me to get down to how some JS internals work.

@Chanran
Copy link
Copy Markdown
Contributor Author

Chanran commented Jan 26, 2026

@zloirock
Sorry about missing the messages. And welcome @johnzhou721 for picking up too. I will also check this these days.

@johnzhou721
Copy link
Copy Markdown
Contributor

@Chanran just curious as to how you are testing performance. I think I've gotten the patch done, but I'm not sure if it is performant.

@Chanran
Copy link
Copy Markdown
Contributor Author

Chanran commented Jan 26, 2026

@Chanran just curious as to how you are testing performance. I think I've gotten the patch done, but I'm not sure if it is performant.

@johnzhou721 There is demo to test. dankogai/js-base64#186 you can try.

@johnzhou721
Copy link
Copy Markdown
Contributor

@Chanran thanks, I've posted instructions on how to modify the demo to work with core-js over at #1503.

I think this can be closed now, as #1503 is passing tests and working fine locally producing the same strings.

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.

4 participants