Are ES6 template literals faster than string concatenation?

35,633

Solution 1

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% slower
String concatenation with variable    89,791,408    ±2.15%    fastest
ES6 with function                     461,358       ±3.12%    99% slower
String 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%    fastest
String concatenation with variable    27,046,298       ±0.48%    44% slower
ES6 with function                     820,441          ±1.10%    98% slower
String 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%    fastest
String concatenation with variable    1,876,993,458    ±0.79%    3% slower
ES6 with function                     539,762          ±5.04%    100% slower
String 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%    fastest
String concatenation with variable    1,355,512,037    ±0.70%    2% slower
ES6 with function                     876,516          ±1.01%    100% slower
String 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.

Solution 2

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:

strConcat
128888890 - 1904ms
strTemplate
128888890 - 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.

Solution 3

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

Solution 4

For a simple test with random numbers as string, both are coming so close in Chrome & FF

Testing in Chrome 58.0.3029 / Windows 10

String literals 2,996,883 ±2.36% fastest

Operator (+) 3,054,078 ±2.01% fastest

Concat function 2,659,391 ±2.35% 13% slower

Testing in Firefox 53.0.2 / Windows 10

String literals 1,923,835 ±1.52% fastest

Operator (+) 1,948,503 ±1.13% fastest

Concat function 1,810,857 ±1.81% 8% slower

Test here at jsperf

Share:
35,633
hurrymaplelad
Author by

hurrymaplelad

Updated on July 06, 2020

Comments

  • hurrymaplelad
    hurrymaplelad almost 4 years

    Does HTML code generation run measurably faster in modern browsers when using string concatenation or template literals in ES6?

    For example:

    String concatenation

    "<body>"+
      "<article>"+
        "<time datetime='" + date.toISOString() +"'>"+ date +"</time>"+
      "</article>"+
    "</body>"
    

    Template literal

    `<body>
      <article>
        <time datetime='${ date.toISOString() }'>${ date }</time>
      </article>
    </body>`
    
  • rattray
    rattray over 7 years
    I ran a similar benchmark and got a similar result. My benchmark included more strings, some of which were longer. Interpolation performs slightly better than concatenation.
  • icl7126
    icl7126 over 7 years
    Firefox 50 64bit - ES6 has same speed as concatenation 1,423,816,207 Ops/s.
  • Nikolai Borisik
    Nikolai Borisik over 7 years
    Safari 9.0 ES6 interpolations faster than concatenation about 34% Chrome 55 still ES6 interpolations much slower Firefox 50 the same speed
  • Armin
    Armin over 6 years
    I'm currently running a new version of my test script. It includes the absolute average mean and the median. It also benchmarks the runtime with 10 variables to replace.
  • FesterCluck
    FesterCluck over 6 years
    Template strings are now an order of magnitude faster than string concatenation. See version 14 of the given jsperf, it is the most accurate & unbiased one can technically get while retaining feature aspects. Version 17 is least biased but unrealistic.
  • Jorge Fuentes González
    Jorge Fuentes González over 4 years
    The jsperf link you passed, in "Revision 1" string literals are still slower than string concatenation under latest Chrome: u.teknik.io/nPmY8.png
  • Andrew Odri
    Andrew Odri over 4 years
    @JorgeFuentesGonzález Yup, just tested on Chrome 79.0.3945 and got a similar result to you... Really interesting, I'll update the post :)
  • Jorge Fuentes González
    Jorge Fuentes González over 4 years
    The jsperf result file got deleted. Uploaded this one without expiration: u.teknik.io/02OVr.png
  • Artur Müller Romanov
    Artur Müller Romanov almost 3 years
    @AndrewOdri Just wanted to point out how much you have helped the community with this post and thank you in the name of all of us :-)
  • Andrew Odri
    Andrew Odri almost 3 years
    Thanks @ArturMüllerRomanov!!! It's really too bad jsperf folded though... It'll be a lot harder to collect crowdsourced data like this for future tests
  • zwcloud
    zwcloud almost 2 years
    @JorgeFuentesGonzález expired
  • Jorge Fuentes González
    Jorge Fuentes González almost 2 years
    @zwcloud yep, teknik somehow changed. I've changed img hosting server since a couple months.