Javascript ES6 模板文字是否比字符串连接更快?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29055518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:48:30  来源:igfitidea点击:

Are ES6 template literals faster than string concatenation?

javascriptstringperformancetemplatesecmascript-6

提问by hurrymaplelad

Has anyone done benchmarks? I'm curious if HTML generation code is faster with string concatenation or with template literals in Node and modern browsers.

有没有人做过基准测试?我很好奇 HTML 生成代码是否在 Node 和现代浏览器中使用字符串连接或模板文字更快。

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>`

回答by Andrew Odri

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

目前似乎字符串连接速度更快: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-harmonyflag enabled.

我测试的是在 Chrome 43.0.2334.0 canary(64 位)上运行,它使用 V8 4.3.31,并#enable-javascript-harmony启用了标志。

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

作为参考,Node.js 上的最新版本(撰写本文时为 0.12.0)使用的是 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.

我确信所有可能应用的性能优化还没有被应用,因此随着 ES6 接近定稿并且这些功能迁移到稳定分支,期望性能会变得更好是合理的。



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.

编辑:感谢@user1329482、@icl7126、Nicolai Borisik 和 FesterCluck 的评论。自从提出这个问题到现在已经过去了大约 2 年,ES6 浏览器的支持已经大大增加,并且进行了大量的性能优化。这里有一些更新

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

编辑:(2020 年 2 月)根据 @JorgeFuentesGonzález 评论和后续确认更新了 Chrome 结果

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

在 Chrome(截至 59.0.3035)中,ES6 字符串文字更快

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.

更新:在 Chrome 中(从 79.0.3945 开始),字符串连接速度更快......请参阅评论。

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

在 Firefox 中(从 57.0.0 开始),ES6 字符串文字更快

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:

在 Safari 中(从 11.0.2 开始),这取决于:

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 fasterin this example.

使用类型转换字符串时,ES6 字符串文字更快。但是,当从字面量调用函数时,在此示例中字符串连接速度更快

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.

如果你真的想深入研究并且需要从 Safari 中榨取每一滴性能,我建议设置测试,看看是否/如何在字面效果性能中查看错误类型的变量和多重引用。

回答by analog-nico

I did a naive test on node.js v6.0.0and 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.

我在node.js v6.0.0上做了一个简单的测试,得到了几乎相同的性能。既然测试如此天真,不要太相信数字。但现在 JIT 编译器似乎生成了非常优化的代码。这让我决定更喜欢模板而不是我的节点应用程序的串联。

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 lento 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.

我曾经len绝对确保优化器不会优化整个循环。无论如何,这仍然是一个非常简单的测试。也许有人可以做一个更复杂的。

回答by Dinesh Rajan

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

对于使用随机数作为字符串的简单测试,两者在 Chrome 和 FF 中都非常接近

Testing in Chrome 58.0.3029 / Windows 10

在 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

字符串文字最快 2,996,883 ±2.36%

操作员 (+) 3,054,078 ±2.01% 最快

Concat 函数 2,659,391 ±2.35% 慢 13%

Testing in Firefox 53.0.2 / Windows 10

在 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

字符串文字 1,923,835 ±1.52% 最快

操作员 (+) 1,948,503 ±1.13% 最快

Concat 函数 1,810,857 ±1.81% 慢 8%

Test here at jsperf

在 jsperf 上测试

回答by Armin

TL;DR

TL; 博士

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).

连接速度更快,更一致。但是对于 1 或 2 个变量,差异很小(对于 1 亿次调用,低于 0.3 秒)。

Edit

编辑

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

在第二次运行之后,连接似乎是两者中速度更快的。



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

因此,我想通过提供一个更广泛的测试来扩展模拟 nico 的答案,并且还(有点)研究了这两个功能的可扩展性。

Code on pastebin

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.

我决定为每个函数使用四个测试用例,前面有一个变量,一个在最后,一个在中间,中间有两个变量。基本设置是一样的。我只使用了 100,000,000 次函数迭代,这些迭代运行了 100 次。我使用相同的机制来防止优化,即获取结果字符串的长度总和并记录下来。我还记录了所需的时间(让我猜测需要多长时间),但也将其保存到一个数组中。

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. startmeans 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. sumis the sum of all 100 runs. avgis the average run, meaning it is sum / 100. sdHere is the easy way out, wikipedia (simple english). minand maxare the minimum and maximum value of a run respectively.

在值t-objects是模板,在值c-objects是串联。start表示变量在开头,mid 表示在中间,end 表示在末尾,double 表示有两个变量。sum是所有 100 次运行的总和。avg是平均运行,这意味着它是sum / 100sd这是一个简单的出路,维基百科(简单英语)minmax分别是运行的最小值和最大值。

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...

由于大多数模板可能不会仅用于字符串中的一个变量,因此可以说坚持连接会产生更好的性能。但区别是(至少现在)非常微小。在使用两个变量进行 100,000,000(1 亿)次评估时,差异仅为 273,58 毫秒,大约四分之一秒……



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

代码在这里

回答by gev

I think that the benchmark above is not useful. The result of interpolation or concatenation hasn't used. So yes, concatenation is pretty fast, because no string coping there and result string have only links to the parent strings. But if you'll try out the result string or compare with another one, the string will be serialized to plane string and, yes it will take some time. So interpolation could be more effective for CPU and memory usage then concatenation in real cases.

我认为上面的基准没有用。未使用插值或连接的结果。所以是的,连接非常快,因为没有字符串在那里处理,结果字符串只有到父字符串的链接。但是,如果您要尝试结果字符串或与另一个字符串进行比较,该字符串将被序列化为平面字符串,是的,这需要一些时间。因此,在实际情况下,插值对于 CPU 和内存使用可能比串联更有效。