Are ES6 template literals faster than string concatenation? Are ES6 template literals faster than string concatenation? javascript javascript

Are ES6 template literals faster than string concatenation?


It seems for the moment string concatenation is faster: http://jsperf.com/es6-string-literals-vs-string-concatenation

ES6 with variable                     19,992,512    ±5.21%    78% slowerString concatenation with variable    89,791,408    ±2.15%    fastestES6 with function                     461,358       ±3.12%    99% slowerString concatenation with function    503,255       ±1.77%    99% slower

I tested was run on Chrome 43.0.2334.0 canary (64-bit), which is using V8 4.3.31, with the #enable-javascript-harmony flag enabled.

For reference, the latest version on Node.js (0.12.0 at the time of writing) is using V8 3.28.73: https://raw.githubusercontent.com/joyent/node/master/ChangeLog

I'm sure all the possible performance optimizations that could be applied have not been applied yet, so it would be reasonable to expect performance to get better as ES6 gets closer to finalization and these features get migrated to the stable branch.


Edit: Thanks for the comments @user1329482, @icl7126, Nicolai Borisik, and FesterCluck. Now that about 2 years have passed since this question was asked, ES6 browser support has greatly increased, and a good amount of performance optimization has taken place. Here are some updates.

Edit: (February 2020) Updated Chrome result based on @JorgeFuentesGonzález comments and subsequent confirmation.

In Chrome (as of 59.0.3035), ES6 string literals are faster:

ES6 with variable                     48,161,401       ±1.07%    fastestString concatenation with variable    27,046,298       ±0.48%    44% slowerES6 with function                     820,441          ±1.10%    98% slowerString concatenation with function    807,088          ±1.08%    98% slower

Update: In Chrome (as of 79.0.3945), String concatenation is faster... See comments.

In Firefox (as of 57.0.0), ES6 string literals are faster:

ES6 with variable                     1,924,610,984    ±0.50%    fastestString concatenation with variable    1,876,993,458    ±0.79%    3% slowerES6 with function                     539,762          ±5.04%    100% slowerString concatenation with function    546,030          ±5.88%    100% slower

In Safari (as of 11.0.2), it depends:

ES6 with variable                     1,382,752,744    ±0.71%    fastestString concatenation with variable    1,355,512,037    ±0.70%    2% slowerES6 with function                     876,516          ±1.01%    100% slowerString concatenation with function    883,370          ±0.79%    100% slower

When using a typecast string, ES6 string literals are faster. However, when calling a function from the literal, string concatenation is faster in this example.

If you really want to go deep and need to squeeze every drop of performance out of Safari, I would suggest setting up tests that see if/how incorrectly typed variables and multiple references within a literal effect performance.


I did a naive test on node.js v6.0.0 and got nearly the same performance. Since the test is so naive, don't believe the numbers too much. But it seems the JIT compiler generates very optimised code nowadays. This let me decide to prefer templates over concatenation for my node apps.

For reference this is the code I used:

'use strict'function strConcat(i) {    return 'abc' + i + 'def'}function strTemplate(i) {    return `abc${i}def`}function run(strategy) {    let before = new Date().getTime()    let len = 0    for ( let i = 0; i < 10000000; i+=1 ) {        len += strategy(i).length    }    console.log(len + ' - ' + ((new Date().getTime()) - before) + 'ms')}console.log('strConcat')run(strConcat)console.log('strTemplate')run(strTemplate)

And the output was:

strConcat128888890 - 1904msstrTemplate128888890 - 1979ms

I used len to absolutely make sure that the optimizer doesn't optimize the whole loop away. Anyway, it is still a very simple test. Maybe someone can make a more sophisticated one.


TL;DR

Concatenation is faster and more consistent regarding its speed.But the difference is very little for 1 or 2 variables (below .3 seconds for 100 million calls).

Edit

After the second run it seems that concatenation is mostly the faster of the two.


So, I wanted to expand analog-nico's answer by providing a test that was more extensive and also looked (a bit) into scalability of the two functions.

Code on pastebin

I decided to use four test cases for each function, having a variable in the front, one at the end, one in the middle and two variables in the middle. The basic setup is the same. I'm just using 100,000,000 iterations of the function and these iterations are run 100 times.I used the same mechanisms to prevent optimization, namely getting the sum of the lengths of the resulting strings and logging it. I also logged the time needed (for me to guess how long it'll take) but also saved it into an array.

Afterwards, I calculated the average, minimum, maximum, and standard deviation for each method.

Here are the results:

{   sum: {     t: {       start: 2072751,       mid: 2338476,       end: 2083695,       double: 2950287     },    c: {       start: 2086059,       mid: 2345551,       end: 2074732,       double: 2922929     }   },  avg: {     t: {       start: 20727.51,      mid: 23384.76,      end: 20836.95,      double: 29502.87     },    c: {       start: 20860.59,      mid: 23455.51,      end: 20747.32,      double: 29229.29     }   },  sd: {    t: {      start: 335.6251329981114,      mid: 282.9490809315344,      end: 286.2220947096852,      double: 216.40844045461824     },    c: {      start: 255.4803356424913,      mid: 221.48744862858484,      end: 238.98242111084238,      double: 209.9309074433776     }   },  min: {     t: {       start: 20490,       mid: 23216,       end: 20588,       double: 29271     },    c: {       start: 20660,       mid: 23258,       end: 20534,       double: 28985     }   },  max: {     t: {       start: 23279,       mid: 25616,       end: 22887,       double: 30843     },    c: {       start: 22603,       mid: 25062,       end: 22403,       double: 30536     }   } }

values in t-objects are for templates, values in c-objects are for concatenation. start means that the variable is at the beginning, mid that it is in the middle, end that it is at the end and double that there are two variables. sum is the sum of all 100 runs. avg is the average run, meaning it is sum / 100. sd Here is the easy way out, wikipedia (simple english). min and max are the minimum and maximum value of a run respectively.

Results

It seems like templates are faster for single variables that are not located at the end of a string, considering that the average is lower and the minimum is lower. If you put a variable at the end of a string or have multiple variables in your string, concatenation is faster.

Although the minimum as well as the average of templates is better than their concatenation counterparts regarding the first two conditions, the standard deviation is consistently worse. The difference seems to shrink with more variables (more tests needed).

Since most templates won't probably be used for only one variable in a string, it is save to say that sticking to concatenation yields a better performance.But the difference is (at least for now) very marginally. At 100,000,000 (100 million) evaluations with two variables, the difference are merely 273,58 ms, about a quarter second...


Second Run

The second run looks somewhat different. Except for the maximum value, average absolute deviation, and standard deviation, every measurement proofed that concatenation is faster than templates.

The three mentioned measurements had lower (thus better) values for templates when the variable was at the end of the string or when there were two variables in the string.

Here are the results:

{  "sum": {    "t": {      "start": 1785103,      "mid": 1826679,      "end": 1719594,      "double": 2110823,      "many": 4153368    },    "c": {      "start": 1720260,      "mid": 1799579,      "end": 1716883,      "double": 2097473,      "many": 3836265    }  },  "avg": {    "t": {      "start": 17851.03,      "mid": 18266.79,      "end": 17195.94,      "double": 21108.23,      "many": 41533.68    },    "c": {      "start": 17202.6,      "mid": 17995.79,      "end": 17168.83,      "double": 20974.73,      "many": 38362.65    }  },  "sd": {    "t": {      "start": 858.7857061572462,      "mid": 886.0941856823124,      "end": 786.5366719994689,      "double": 905.5376950188214,      "many": 1744.9005638144542    },    "c": {      "start": 599.0468429096342,      "mid": 719.1084521127534,      "end": 935.9367719563112,      "double": 991.5642274204934,      "many": 1465.1116774840066    }  },  "aad": {    "t": {      "start": 579.1207999999996,      "mid": 576.5628000000003,      "end": 526.8268,      "double": 586.9651999999998,      "many": 1135.9432000000002    },    "c": {      "start": 467.96399999999966,      "mid": 443.09220000000016,      "end": 551.1318000000008,      "double": 610.2321999999999,      "many": 1020.1310000000003    }  },  "min": {    "t": {      "start": 16932,      "mid": 17238,      "end": 16387,      "double": 20016,      "many": 39327    },    "c": {      "start": 16477,      "mid": 17137,      "end": 16226,      "double": 19863,      "many": 36424    }  },  "max": {    "t": {      "start": 23310,      "mid": 24102,      "end": 21258,      "double": 26883,      "many": 49103    },    "c": {      "start": 19328,      "mid": 23203,      "end": 22859,      "double": 26875,      "many": 44352    }  },  "median": {    "t": {      "start": 17571,      "mid": 18062,      "end": 16974,      "double": 20874,      "many": 41171.5    },    "c": {      "start": 16893.5,      "mid": 18213,      "end": 17016.5,      "double": 20771,      "many": 38849    }  }}

The code is here