Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is string concatenation faster than array join?

People also ask

Is concatenation faster than join?

Doing N concatenations requires creating N new strings in the process. join() , on the other hand, only has to create a single string (the final result) and thus works much faster.

Is join faster than concatenation Python?

String join is significantly faster then concatenation. Why? Strings are immutable and can't be changed in place. To alter one, a new representation needs to be created (a concatenation of the two).

Is concat faster?

concat function is 50 times faster than using the DataFrame. append version. With multiple append , a new DataFrame is created at each iteration, and the underlying data is copied each time.

Is string concatenation slow?

Each time strcat calls, the loop will run from start to finish; the longer the string, the longer the loop runs. Until the string is extensive, the string addition takes place very heavy and slow.


Browser string optimizations have changed the string concatenation picture.

Firefox was the first browser to optimize string concatenation. Beginning with version 1.0, the array technique is actually slower than using the plus operator in all cases. Other browsers have also optimized string concatenation, so Safari, Opera, Chrome, and Internet Explorer 8 also show better performance using the plus operator. Internet Explorer prior to version 8 didn’t have such an optimization, and so the array technique is always faster than the plus operator.

— Writing Efficient JavaScript: Chapter 7 – Even Faster Websites

The V8 javascript engine (used in Google Chrome) uses this code to do string concatenation:

// ECMA-262, section 15.5.4.6
function StringConcat() {
  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
    throw MakeTypeError("called_on_null_or_undefined", ["String.prototype.concat"]);
  }
  var len = %_ArgumentsLength();
  var this_as_string = TO_STRING_INLINE(this);
  if (len === 1) {
    return this_as_string + %_Arguments(0);
  }
  var parts = new InternalArray(len + 1);
  parts[0] = this_as_string;
  for (var i = 0; i < len; i++) {
    var part = %_Arguments(i);
    parts[i + 1] = TO_STRING_INLINE(part);
  }
  return %StringBuilderConcat(parts, len + 1, "");
}

So, internally they optimize it by creating an InternalArray (the parts variable), which is then filled. The StringBuilderConcat function is called with these parts. It's fast because the StringBuilderConcat function is some heavily optimized C++ code. It's too long to quote here, but search in the runtime.cc file for RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) to see the code.


Firefox is fast because it uses something called Ropes (Ropes: an Alternative to Strings). A rope is basically just a DAG, where every Node is a string.

So for example, if you would do a = 'abc'.concat('def'), the newly created object would look like this. Of course this is not exactly how this looks like in memory, because you still need to have a field for the string type, length and maybe other.

a = {
 nodeA: 'abc',
 nodeB: 'def'
}

And b = a.concat('123')

b = {
  nodeA: a, /* {
             nodeA: 'abc',
             nodeB: 'def'
          } */
  nodeB: '123'
}           

So in the simplest case the VM has to do nearly no work. The only problem is that this slows down other operations on the resulting string a little bit. Also this of course reduces memory overhead.

On the other hand ['abc', 'def'].join('') would usually just allocate memory to lay out the new string flat in memory. (Maybe this should be optimized)


I know this is an old thread, but your test is incorrect. You are doing output += myarray[i]; while it should be more like output += "" + myarray[i]; because you've forgot, that you have to glue items together with something. The concat code should be something like:

var output = myarray[0];
for (var i = 1, len = myarray.length; i<len; i++){
    output += "" + myarray[i];
}

That way, you are doing two operations instead of one due to glueing elements together.

Array.join() is faster.


For large amount of data join is faster, so the question is stated incorrectly.

let result = "";
let startTime = new Date().getTime();
for (let i = 0; i < 2000000; i++) {
    result += "x";
}
console.log("concatenation time: " + (new Date().getTime() - startTime));

startTime = new Date().getTime();
let array = new Array(2000000);
for (let i = 0; i < 2000000; i++) {
    array[i] = "x";
}
result = array.join("");
console.log("join time: " + (new Date().getTime() - startTime));

Tested on Chrome 72.0.3626.119, Firefox 65.0.1, Edge 42.17134.1.0. Note that it is faster even with the array creation included!