ES6 템플릿 리터럴이 문자열 연결보다 빠릅니까?
벤치 마크를 한 사람이 있습니까? HTML 생성 코드가 문자열 연결 또는 Node 및 최신 브라우저의 템플릿 리터럴을 사용하여 더 빠른지 궁금합니다.
예를 들면 :
문자열 연결
"<body>"+
"<article>"+
"<time datetime='" + date.toISOString() +"'>"+ date +"</time>"+
"</article>"+
"</body>"
템플릿 리터럴
`<body>
<article>
<time datetime='${ date.toISOString() }'>${ date }</time>
</article>
</body>`
순간 문자열 연결이 더 빠른 것 같습니다 : 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
테스트는 #enable-javascript-harmony
플래그가 활성화 된 V8 4.3.31을 사용하는 Chrome 43.0.2334.0 canary (64 비트)에서 실행되었습니다 .
참고로 Node.js의 최신 버전 (작성 당시 0.12.0)은 V8 3.28.73을 사용하고 있습니다 : https://raw.githubusercontent.com/joyent/node/master/ChangeLog
적용 할 수있는 가능한 모든 성능 최적화가 아직 적용되지 않았을 것이므로 ES6가 최종화에 가까워지고 이러한 기능이 안정 브랜치로 마이그레이션됨에 따라 성능이 향상 될 것으로 기대하는 것이 합리적입니다.
편집 : @ user1329482, @ icl7126, Nicolai Borisik 및 FesterCluck 의견에 감사드립니다. 이 질문을받은 지 약 2 년이 지났으므로 ES6 브라우저 지원이 크게 증가했으며 상당한 성능 최적화가 이루어졌습니다. 다음은 몇 가지 업데이트입니다.
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
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
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
타입 캐스트 문자열을 사용할 때 ES6 문자열 리터럴이 더 빠릅니다 . 그러나 리터럴에서 함수를 호출 할 때이 예제 에서는 문자열 연결이 더 빠릅니다 .
정말로 깊이 들어가서 Safari의 모든 성능 저하를 짜 내야한다면 문자 그대로 효과 성능 내에서 변수와 여러 참조를 잘못 입력했는지 여부를 확인하는 테스트를 설정하는 것이 좋습니다.
node.js v6.0.0 에서 순진한 테스트를 했고 거의 동일한 성능을 얻었 습니다 . 테스트가 너무 순진하기 때문에 숫자를 너무 많이 믿지 마십시오. 그러나 오늘날 JIT 컴파일러는 매우 최적화 된 코드를 생성하는 것 같습니다. 이를 통해 노드 앱에 대한 연결보다 템플릿을 선호하도록 결정할 수 있습니다.
참고로 이것은 내가 사용한 코드입니다.
'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)
결과는 다음과 같습니다.
strConcat
128888890 - 1904ms
strTemplate
128888890 - 1979ms
저는 len
옵티마이 저가 전체 루프를 최적화하지 않도록 절대적으로 확인했습니다. 어쨌든 여전히 매우 간단한 테스트입니다. 누군가가 더 정교한 것을 만들 수있을 것입니다.
난수를 문자열로 사용하는 간단한 테스트의 경우 둘 다 Chrome 및 FF에서 매우 가깝습니다.
Chrome 58.0.3029 / Windows 10에서 테스트
문자열 리터럴 2,996,883 ± 2.36 % 가장 빠름
연산자 (+) 3,054,078 ± 2.01 % 가장 빠름
Concat 함수 2,659,391 ± 2.35 % 13 % 느림
Firefox 53.0.2 / Windows 10에서 테스트
문자열 리터럴 1,923,835 ± 1.52 % 가장 빠름
연산자 (+) 1,948,503 ± 1.13 % 가장 빠름
Concat 기능 1,810,857 ± 1.81 % 8 % 느림
TL; DR
연결 속도와 관련하여 더 빠르고 일관성이 있습니다. 그러나 변수 1 개 또는 2 개의 차이는 거의 없습니다 (1 억 호출의 경우 .3 초 미만).
편집하다
두 번째 실행 후 연결이 대부분 두 가지 중 더 빠른 것 같습니다.
그래서 저는 더 광범위하고 두 기능의 확장 성을 (조금) 살펴본 테스트를 제공하여 analog-nico의 답변 을 확장하고 싶었습니다 .
각 함수에 대해 4 개의 테스트 케이스를 사용하기로 결정했습니다. 변수는 앞쪽에, 끝에 하나, 중간에 하나, 중간에 두 개 있습니다. 기본 설정은 동일합니다. 저는 함수의 100,000,000 반복을 사용하고 있으며 이러한 반복은 100 번 실행됩니다. 최적화를 방지하기 위해 동일한 메커니즘을 사용했습니다. 즉, 결과 문자열의 길이 합계를 가져와 로깅했습니다. 또한 필요한 시간을 기록했지만 (얼마나 걸릴지 추측하기 위해) 배열에 저장했습니다.
그 후 각 방법의 평균, 최소, 최대 및 표준 편차를 계산했습니다.
결과는 다음과 같습니다.
{
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
}
}
}
t
-objects의 값은 템플릿 용이고 c
-objects의 값은 연결 용입니다. start
변수가 시작 부분에 있고 중간에 있음을 의미하고 중간에 있음을 의미하며 끝이 끝에 있음을 의미하며 두 개의 변수가 있음을 의미합니다. sum
100 회 실행의 합계입니다. avg
평균 실행입니다 sum / 100
. sd
여기에 쉬운 방법, wikipedia (simple english)가 있습니다. min
그리고 max
각각 실행의 최소 및 최대 값입니다.
결과
평균이 더 낮고 최소값이 더 낮다는 점을 고려할 때 문자열 끝에 위치하지 않는 단일 변수의 경우 템플릿이 더 빠릅니다. 문자열 끝에 변수를 넣거나 문자열에 여러 변수가 있으면 연결이 더 빠릅니다.
템플릿의 최소값과 평균이 처음 두 조건과 관련하여 연결 대응 항목보다 낫지 만 표준 편차는 지속적으로 더 나쁩니다. 변수가 많을수록 차이가 줄어드는 것 같습니다 (더 많은 테스트가 필요함).
대부분의 템플릿은 문자열에서 하나의 변수에만 사용되지 않을 것이므로 연결을 고수하면 더 나은 성능을 얻을 수 있습니다. 그러나 그 차이는 (적어도 현재로서는) 매우 미미합니다. 두 변수를 사용한 100,000,000 (1 억) 평가에서 차이는 약 1/4 초인 273,58ms에 불과합니다.
두 번째 실행
두 번째 실행은 다소 다르게 보입니다. 최대 값, 평균 절대 편차 및 표준 편차를 제외하고 모든 측정은 연결이 템플릿보다 빠르다는 것을 증명했습니다.
언급 된 세 개의 측정 값은 변수가 문자열의 끝에 있거나 문자열에 두 개의 변수가있을 때 템플릿에 대해 더 낮은 값을 가졌습니다.
결과는 다음과 같습니다.
{
"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
}
}
}
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.
'programing tip' 카테고리의 다른 글
작성 및 업데이트시 MySQL CURRENT_TIMESTAMP (0) | 2020.11.21 |
---|---|
Python : 선택적 함수 매개 변수가 설정되었는지 확인하는 방법 (0) | 2020.11.21 |
Tensorflow에서 Poolallocator 메시지를 해석하는 방법은 무엇입니까? (0) | 2020.11.21 |
다른 요소 앞에 오는 요소를 선택하기위한 CSS 선택기? (0) | 2020.11.21 |
URL을 열려면 운영 체제를 호출 하시겠습니까? (0) | 2020.11.20 |