Speed-up Array.join("")
Reported by
ivan.kuc...@gmail.com,
Oct 27 2017
|
||||||
Issue description
UserAgent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36
Steps to reproduce the problem:
1. In my work, I often use a "string-builder": I put many strings into an array and then concatenate them by calling arr.join("");
2. Right now, I have a practical case, where I need to concat 40 millions single-character strings.
I made a demo: http://www.ivank.net/veci/join_test.html
It joins 40 millions single-character strings and prints the computation time into the console.
What is the expected behavior?
What went wrong?
In Chrome, it takes 5700 ms, while in Firefox, it takes 360 ms (16x faster).
Could you speed-up joining with an empty string? It is often used in practice as a "string-builder".
Did this work before? N/A
Chrome version: 62.0.3202.62 Channel: n/a
OS Version: 6.1 (Windows 7, Windows Server 2008 R2)
Flash Version: Shockwave Flash 27.0 r0
,
Oct 27 2017
Some related notes:
Array#join is a bit faster in Chrome Canary 64, but still takes more than 3 seconds.
Possible workarounds for this *specific case* that match or even outperform Firefox on the original code:
* store character codes, join in chunks (~350ms, Canary: 200ms)
var chrs = [];
for (var i=0; i<40000000; i++) chrs.push(64+(i&31));
var strs = [];
for (var i = 0; i<chrs.length/10e3; i++)
strs.push(String.fromCharCode.apply(null, chrs.slice(i * 10e3, (i + 1) * 10e3)));
var str = strs.join('');
* store character codes, use TextDecoder (~100ms)
var chrs = [];
for (var i=0; i<40000000; i++) chrs.push(64+(i&31));
var str = new TextDecoder().decode(new Uint8Array(chrs));
,
Oct 28 2017
Wooooow ... Precisely, I am parsing a 40 MB JSON file from an ArrayBuffer. First, I parse UTF8 (convert bytes into Unicode codes - integers), then I call String.fromCharCode on each code. Then I concatenate it with .join(""). Then I can give that string to JSON.parse();
I was so desperate that I wrote my own JSON parser, that works directly with char codes (avoiding a long string). It seems like TextDecoder can save me a lot of work (I never heard about it before). But it is still not supported in Edge :(
,
Oct 30 2017
,
Oct 30 2017
For posterity, the demo in #0 is:
var chrs = [];
for(var i=0; i<40000000; i++) chrs.push(String.fromCharCode(64+(i&31)));
var time = Date.now();
var str = chrs.join("");
console.log(Date.now()-time);
,
Dec 15 2017
,
Sep 12
Guys, I think we can close it, since TextDecoder() solves my problem, so I don't need fast string joining anymore.
,
Sep 12
FYI the new Array.p.join Torque implementation is currently under review at https://crrev.com/c/1196693.
,
Oct 25
Peter's new join impl has landed, this is what I now see locally in d8:
$ out/release/d8 tmp.js
802
$ cat tmp.js
const chrs = [];
const chr = String.fromCharCode(64+(i&31));
for (var i=0; i<40000000; i++) chrs.push(chr);
const time = Date.now();
const str = chrs.join("");
console.log(Date.now()-time, str.length);
|
||||||
►
Sign in to add a comment |
||||||
Comment 1 by chrishtr@chromium.org
, Oct 27 2017