[javascript] ES6 템플릿 리터럴이 문자열 연결보다 빠릅니까?

ES6에서 문자열 연결 또는 템플릿 리터럴을 사용할 때 최신 브라우저에서 HTML 코드 생성이 눈에 띄게 빠르게 실행됩니까?

예를 들면 :

문자열 연결

"<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 카나리아 (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 브라우저 지원이 크게 증가했으며 상당한 성능 최적화가 이루어졌습니다. 다음은 몇 가지 업데이트 입니다.

편집 : (2020 년 2 월) @ JorgeFuentesGonzález 댓글 및 후속 확인을 기반으로 Chrome 결과가 업데이트되었습니다 .

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

업데이트 : Chrome (79.0.3945 기준)에서 문자열 연결이 더 빠릅니다 . 주석을 참조하십시오.

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 % 느림

여기 jsperf에서 테스트


답변

TL; DR

연결 속도와 관련하여 더 빠르고 일관성이 있습니다. 그러나 변수 1 개 또는 2 개의 차이는 거의 없습니다 (1 억 호출의 경우 .3 초 미만).

편집하다

두 번째 실행 후 연결이 대부분 두 가지 중 더 빠른 것 같습니다.


그래서 저는 더 광범위하고 두 기능의 확장 성을 (조금) 살펴본 테스트를 제공하여 analog-nico의 답변 을 확장하고 싶었습니다 .

pastebin의 코드

각 함수에 대해 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변수가 시작 부분에 있고 중간에 있음을 의미하고 중간에 있음을 의미하며 끝이 끝에 있음을 의미하며 두 개의 변수가 있음을 의미합니다. sum100 회 실행의 합계입니다. 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
    }
  }
}

코드는 여기에 있습니다


답변

위의 벤치 마크는 유용하지 않다고 생각합니다. 보간 또는 연결의 결과가 사용되지 않았습니다. 예, 연결이 매우 빠릅니다. 거기에 문자열을 처리하지 않고 결과 문자열에 상위 문자열에 대한 링크 만 있기 때문입니다. 그러나 결과 문자열을 시도하거나 다른 문자열과 비교하면 문자열이 평면 문자열로 직렬화되며 시간이 좀 걸립니다. 따라서 보간은 CPU 및 메모리 사용량에 더 효과적 일 수 있으며 실제 경우에는 연결이 가능합니다.


답변