+ 연산자는 StringBuffer.append ()보다 성능이 떨어집니다.


91

우리 팀에서는 일반적으로 다음과 같이 문자열 연결을 수행합니다.

var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");

분명히 다음은 훨씬 더 읽기 쉽습니다.

var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";

그러나 JS 전문가들은 +운영자가 StringBuffer.append(). 정말 사실인가요?


92
자바 스크립트에는 StringBuffer가 없습니다
Tomas

7
Don, Java를 언급 했습니까?
James McMahon

내 경험은 [].join('')정말 유선적인 동작을
보여줬 기

1
여기서 기본적인 질문은 문자열 연결에 관한 것임을 알고 있지만 이와 같은 html 요소를 만들 때는주의해야합니다. (가) 경우 예를 깰 수 url포함 '\n.
styfle 2013-07-24

답변:


46

Internet Explorer는 오늘날 세계에서이 문제를 겪고있는 유일한 브라우저입니다. (버전 5, 6 및 7은 개가 느 렸습니다. 8은 동일한 성능 저하를 보여주지 않습니다.) 더욱이 IE는 문자열이 길수록 느려집니다.

연결할 긴 문자열이있는 경우 반드시 array.join 기술을 사용하십시오. (또는 가독성을 위해이 주위에 StringBuffer 래퍼가 있습니다.) 그러나 문자열이 짧다면 신경 쓰지 마십시오.


102

귀하의 예는 성능이 크게 다를 가능성이 거의 없다는 점에서 좋은 예가 아닙니다. 귀하의 예제에서 가독성은 성능을 능가해야합니다. 왜냐하면 하나와 다른 하나의 성능 향상은 무시할 수 있기 때문입니다. 배열 (StringBuffer)의 이점은 많은 연결을 수행하는 경우에만 분명합니다. 그래도 마일리지는 브라우저에 따라 크게 달라질 수 있습니다.

다음은 다양한 브라우저에서 모든 다른 JavaScript 연결 방법을 사용하여 성능을 보여주는 자세한 성능 분석입니다. 스트링 성능 및 분석

join () 한 번, concat () 한 번, join () for, + = for, concat () for

더보기 :
Ajaxian >> IE의 문자열 성능 : Array.join 대 + = 계속


9
그래프와 관련하여 명확하지 않은 경우; 낮을수록 좋습니다.
Teekin

1
"첫 번째는 IE7의 성능 향상으로 더 이상 대규모 문자열 작업을 수행 할 때 대체 경로 사용을 고려할 필요가 없습니다. 반복적 인 상황에서 Array.join을 사용하면 동일한 상황에서 + =를 사용하는 것보다 큰 이점이 없습니다. 또한 IE6과의 차이점은 특정 버전에 대해 포크하지 않아도 될만큼 약간의 차이가있었습니다. "
Chris S

2
@Chris, 그건 사실이 아닙니다. 이러한 두 개의 바이올린을 비교 IE7 : jsfiddle.net/9uS4n/5를 (빠른) 대 jsfiddle.net/9uS4n/2 (느린). 이 join()기술을 사용하면 성능이 1000 배 이상 향상되는 것으로 보입니다 .
Kirk Woll 2011

좋은 설명입니다. 또한 이것을 검토하십시오 : iliadraznin.com/2012/03/…
will824 2013-07-23

37

예, 사실이지만 신경 쓰지 마세요. 읽기 쉬운 것을 선택하십시오. 앱을 벤치마킹해야한다면 병목 현상에 집중하세요.

문자열 연결이 병목 현상이되지 않을 것이라고 생각합니다.


31

Michael Haren 과 동의 .

또한 성능이 실제로 문제가되는 경우 어레이 및 조인 사용을 고려하십시오.

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));

3
정답이 선택되었다는 것을 알고 있지만이 답변에는 더 유용한 예가 있습니다.
Jason Sperske 2010

1
와우, 와우. 이러한 두 개의 바이올린을 비교 IE7 : jsfiddle.net/9uS4n/5를 (빠른) 대 jsfiddle.net/9uS4n/2 (느린). 이 기술을 사용하면 성능이 1000 배 이상 향상되는 것으로 보입니다.
Kirk Woll 2011

@KirkWoll : 결과를 쉽게 비교할 수 있도록 앞으로 jsPerf 를 사용하고 싶을 수도 있습니다.
rvighne

나는 최근에 .NET StringBuilder와 비슷한 코드 스타일을하고있다. var sb = []; sb.push ( "섹션 1"); sb.push ( "섹션 2"); return sb.join ( '');
Sam Jones

이 jsPerf jsperf.com/join-concat/2stackoverflow.com/questions/16696632/… 에서 언급 한 +=것이 더 빠르다 는 것을 나타냅니다 .
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

18

이 시도:

var s = ["<a href='", url, "'>click here</a>"].join("");

글쎄, 귀하의 답변에 링크 된 게시물은 내 대답이 제안하는 Array.join의 "신화"를 반증하려고 특별히 시도합니다. 그래서 아마 아닐 것입니다. 나는 단지 내가 실제로 더 빠르다고 본 것을 게시했다.
Rahul

이 문자열 연결 방법을 좋아하십시오.
bkwdesign 2014 년

8

이미 일부 사용자가 언급했듯이 작은 문자열에는 관련이 없습니다.

그리고 Firefox, Safari 또는 Google Chrome의 새로운 JavaScript 엔진은

"<a href='" + url + "'>click here</a>";

빠르다

["<a href='", url, "'>click here</a>"].join("");

8

JavaScript에는 네이티브 StringBuffer 객체가 없으므로 사용중인 라이브러리 또는 비정상적인 호스트 환경 (예 : 브라우저가 아님)의 기능에서 가져온 것이라고 가정합니다.

네이티브 StringBuffer 객체가 할 수 있지만 라이브러리 (JS로 작성된)가 더 빨리 생성되지 않을 것입니다. 확실한 대답은 프로파일 러에서 찾을 수 있습니다 (브라우저에서 실행중인 경우 Firebug는 Firefox에서 찾을 수있는 JS 엔진 용 프로파일 러를 제공합니다).


6

Knuth의 말에 따르면, "조기 최적화는 모든 악의 근원입니다!" 어느 쪽이든 작은 방어는 결국 많은 영향을 미치지 않을 것입니다. 더 읽기 쉬운 것을 선택하겠습니다.


1
전통적으로 StringBuffer는 연결을 통해 사용됩니다. 전자는 O (N) 시간 복잡도를 갖는 반면 후자는 O (N ^ 2)이므로 차이가 큰 N (그러나 작은 N의 경우는 아님)에 중요합니다. 어쨌든 사용 환경에 따라 JavaScript에서는 O (N ^ 2) 시나리오가 아닐 수 있습니다.
redcalx 2011-08-30

4

읽기 쉬운 방법은 코드를 볼 때 사람이 지각 할 수있는 시간을 절약하는 반면, "빠른"방법은 사람들이 페이지를 탐색 할 때인지 할 수없고 무시할 수있는 시간 만 낭비합니다.

이 게시물이 절름발이라는 것을 알고 있지만 실수로 이것이 다른 스레드라고 생각하여 완전히 다른 것을 게시했으며 게시물을 삭제하는 방법을 모릅니다. 내 잘못이야...


3

빠른 벤치 마크를 설정하고 jspref.com을 사용하여 Javascript 성능 변화를 확인하는 것은 매우 쉽습니다. . 이 질문을 받았을 때 아마 없었을 것입니다. 그러나이 질문에 걸림돌이되는 사람들은 사이트를 살펴보아야합니다.

http://jsperf.com/string-concat-methods-test 에서 다양한 연결 방법에 대한 빠른 테스트를 수행했습니다 .


지금은 + 연산자와의 연결이 확실히 갈 길인 것처럼 보입니다. 내가 잘못 읽지 않는 한. 전적으로 그럴듯합니다.
Richard

2

다음과 같은 기능적 스타일을 사용하고 싶습니다.

function href(url,txt) {
  return "<a href='" +url+ "'>" +txt+ "</a>"
}

function li(txt) {
  return "<li>" +txt+ "</li>"
}

function ul(arr) {
  return "<ul>" + arr.map(li).join("") + "</ul>"
}

document.write(
  ul(
    [
      href("http://url1","link1"),
      href("http://url2","link2"),
      href("http://url3","link3")
    ]
  )
)

이 스타일은 읽기 쉽고 투명 해 보입니다. 그것은 코드의 반복을 줄이는 유틸리티의 생성으로 이어집니다.

이것은 또한 중간 문자열을 자동으로 사용하는 경향이 있습니다.


1

내가 아는 한 모든 연결은 메모리 재 할당을 의미합니다. 따라서 문제는이를 수행하는 데 사용되는 연산자가 아닙니다. 해결책은 연결 수를 줄이는 것입니다. 예를 들어 가능하면 반복 구조 외부에서 연결을 수행하십시오.


이것은 실제로 나쁜 조언이 아니며 왜 그렇게 많이 투표되었는지 모르겠습니다. 구체적인 질문에 대한 답은 아니지만 일반적으로 좋은 조언으로 인정받을 가치가 있습니다.
eyelidlessness

0

예, 일반적인 벤치 마크에 따르면. 예 : http://mckoss.com/jscript/SpeedTrial.htm .

그러나 작은 줄의 경우 이것은 관련이 없습니다. 매우 큰 현의 연주에만 관심이 있습니다. 게다가 대부분의 JS 스크립트에서 병목은 문자열 조작이 충분하지 않기 때문에 거의 발생하지 않습니다.

DOM 조작을 보는 것이 좋습니다.


Link is dead .. https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm 은 웹 아카이브 버전을 가리 킵니다.
Tony
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.