ist der Operator + weniger performant als StringBuffer.append ()

91

In meinem Team konzentrieren wir uns normalerweise wie folgt:

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

Offensichtlich ist Folgendes viel besser lesbar:

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

Die JS-Experten behaupten jedoch, dass der +Bediener weniger leistungsfähig ist als StringBuffer.append(). Ist das wirklich wahr?

Dónal
quelle
92
Es gibt keinen StringBuffer in Javascript
Tomas
7
Don, haben Sie sich auf Java bezogen?
James McMahon
Meine Erfahrung war, dass [].join('')sich ein wirklich verdrahtetes Verhalten gezeigt hat, also
gehe
1
Ich weiß, dass die grundlegende Frage hier die Verkettung von Zeichenfolgen betrifft, aber Sie sollten beim Erstellen solcher HTML-Elemente Vorsicht walten lassen. Ihr Beispiel könnte brechen, wenn das urlenthält 'oder \n.
Styfle
Mögliches Duplikat der effizientesten Methode zum Verketten von Zeichenfolgen in JavaScript?
Ciro Santilli 法轮功 冠状 病 六四.

Antworten:

46

Internet Explorer ist der einzige Browser, der in der heutigen Welt wirklich darunter leidet. (Die Versionen 5, 6 und 7 waren hundeschwach. 8 zeigt nicht die gleiche Verschlechterung.) Außerdem wird der IE immer langsamer, je länger Ihre Saite ist.

Wenn Sie lange Zeichenfolgen verketten müssen, verwenden Sie auf jeden Fall eine array.join-Technik. (Oder ein StringBuffer-Wrapper, um die Lesbarkeit zu verbessern.) Aber wenn Ihre Zeichenfolgen kurz sind, stören Sie nicht.

pcorcoran
quelle
102

Ihr Beispiel ist insofern nicht gut, als es sehr unwahrscheinlich ist, dass sich die Leistung erheblich unterscheidet. In Ihrem Beispiel sollte die Lesbarkeit die Leistung übertreffen, da der Leistungsgewinn von einem gegenüber dem anderen vernachlässigbar ist. Die Vorteile eines Arrays (StringBuffer) werden nur deutlich, wenn Sie viele Konzentrationen durchführen. Selbst dann kann Ihr Kilometerstand sehr stark von Ihrem Browser abhängen.

Hier ist eine detaillierte Leistungsanalyse, die die Leistung unter Verwendung aller verschiedenen JavaScript-Verkettungsmethoden in vielen verschiedenen Browsern zeigt. String-Leistung und Analyse

join () einmal, concat () einmal, join () für, + = für, concat () für

Mehr:
Ajaxian >> String-Leistung im IE: Array.join vs + = Fortsetzung

Eric Schoonover
quelle
9
In Bezug auf das Diagramm, falls es nicht offensichtlich ist; weniger ist besser.
Teekin
1
"Bei den Leistungsverbesserungen mit IE7 müssen wir zunächst nicht mehr die Verwendung eines alternativen Pfads in Betracht ziehen, wenn Sie Zeichenfolgenoperationen in großem Maßstab ausführen. Die Verwendung von Array.join in einer iterativen Situation bietet keine größeren Vorteile als die Verwendung von + = in derselben Situation. Darüber hinaus waren die Unterschiede zu IE6 so gering, dass Sie sich nicht die Mühe machen mussten, nach dieser bestimmten Version zu suchen. "
Chris S
2
@ Chris, das stimmt nicht. Vergleichen Sie diese beiden Geigen in IE7 : jsfiddle.net/9uS4n/5 (schnell) vs. jsfiddle.net/9uS4n/2 (langsam). Es scheint eine mindestens 1000-fache Verbesserung der Leistung unter Verwendung der join()Technik zu geben.
Kirk Woll
Schöne Erklärung. Bitte überprüfen Sie auch dies: iliadraznin.com/2012/03/…
will824
37

Ja, es ist wahr, aber es sollte dich nicht interessieren. Entscheide dich für die, die leichter zu lesen ist. Wenn Sie Ihre App bewerten müssen, konzentrieren Sie sich auf die Engpässe.

Ich würde vermuten, dass die Verkettung von Zeichenfolgen nicht Ihr Engpass sein wird.

Michael Haren
quelle
31

Einverstanden mit Michael Haren .

Berücksichtigen Sie auch die Verwendung von Arrays und Joins, wenn die Leistung tatsächlich ein Problem darstellt.

var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));
Frank Krueger
quelle
3
Ich weiß, dass eine richtige Antwort ausgewählt wurde, aber diese Antwort hat ein nützlicheres Beispiel.
Jason Sperske
1
Wow einfach wow. Vergleichen Sie diese beiden Geigen in IE7 : jsfiddle.net/9uS4n/5 (schnell) vs. jsfiddle.net/9uS4n/2 (langsam). Mit dieser Technik scheint sich die Leistung mindestens 1000-mal zu verbessern.
Kirk Woll
@KirkWoll: Vielleicht möchten Sie in Zukunft jsPerf verwenden, damit wir die Ergebnisse leicht vergleichen können.
Rvighne
Ich habe dies auch in letzter Zeit getan, ähnlich wie ein .NET StringBuilder, var sb = []; sb.push ("Abschnitt 1"); sb.push ("Abschnitt 2"); return sb.join ('');
Sam Jones
Dieser jsPerf jsperf.com/join-concat/2 , der unter: stackoverflow.com/questions/16696632/… erwähnt wird, scheint darauf hinzudeuten, dass er +=schneller ist.
Ciro Santilli 法轮功 冠状 病 六四.
18

Versuche dies:

var s = ["<a href='", url, "'>click here</a>"].join("");
Rahul
quelle
Nun, der Beitrag, auf den Sie in Ihrer Antwort verlinkt haben, versucht speziell, den "Mythos" von Array.join zu widerlegen, den meine Antwort vorschlägt. Also vielleicht auch nicht. Ich habe lediglich das gepostet, was ich in der Praxis als schneller gesehen habe.
Rahul
Ich liebe diese Methode der String Concat.
bkwdesign
8

Wie bereits einige Benutzer bemerkt haben: Dies ist für kleine Zeichenfolgen irrelevant.

Und neue JavaScript-Engines in Firefox, Safari oder Google Chrome optimieren dies

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

ist so schnell wie

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

JavaScript hat kein natives StringBuffer-Objekt, daher gehe ich davon aus, dass es aus einer von Ihnen verwendeten Bibliothek oder einer Funktion einer ungewöhnlichen Host-Umgebung (dh keinem Browser) stammt.

Ich bezweifle, dass eine Bibliothek (in JS geschrieben) etwas schneller produzieren würde, obwohl ein natives StringBuffer-Objekt dies könnte. Die endgültige Antwort finden Sie mit einem Profiler (wenn Sie in einem Browser ausgeführt werden, stellt Firebug Ihnen einen Profiler für die in Firefox enthaltene JS-Engine zur Verfügung).

QUentin
quelle
6

Mit den Worten von Knuth: "Vorzeitige Optimierung ist die Wurzel allen Übels!" Die geringe Abweichung in beide Richtungen wird am Ende höchstwahrscheinlich keine große Wirkung haben. Ich würde die besser lesbare wählen.

William Keller
quelle
1
Traditionell wird StringBuffer über die Verkettung verwendet, da der erstere eine O (N) -Zeitkomplexität aufweist, während der letztere als O (N ^ 2) gilt. Daher ist der Unterschied für großes N signifikant (jedoch nicht für kleines N). In jedem Fall ist das O (N ^ 2) -Szenario in JavaScript je nach verwendeter Umgebung möglicherweise nicht der Fall.
Redcalx
4

Die leichter zu lesende Methode spart dem Menschen spürbar viel Zeit beim Betrachten des Codes, während die "schnellere" Methode nur unmerklich und wahrscheinlich vernachlässigbar viel Zeit verschwendet, wenn Benutzer die Seite durchsuchen.

Ich weiß, dass dieser Beitrag lahm ist, aber ich habe versehentlich etwas ganz anderes gepostet, weil ich dachte, dies sei ein anderer Thread, und ich weiß nicht, wie ich Beiträge löschen soll. Mein Fehler...

Ed Kern
quelle
3

Mit jspref.com ist es ziemlich einfach, einen schnellen Benchmark einzurichten und die Leistungsvarianten von Javascript zu überprüfen . Was wahrscheinlich nicht da war, als diese Frage gestellt wurde. Aber für Leute, die über diese Frage stolpern, sollten sie sich auf der Baustelle umsehen.

Unter http://jsperf.com/string-concat-methods-test habe ich verschiedene Verkettungsmethoden kurz getestet .

James McMahon
quelle
Demnach sieht es heutzutage so aus, als wäre die Verkettung mit dem Operator + definitiv der richtige Weg. Es sei denn, ich lese es falsch. Welches ist durchaus plausibel.
Richard
2

Ich verwende gerne funktionale Stile wie:

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")
    ]
  )
)

Dieser Stil sieht lesbar und transparent aus. Dies führt zur Erstellung von Dienstprogrammen, die die Wiederholung von Code reduzieren.

Dies neigt auch dazu, Zwischenzeichenfolgen automatisch zu verwenden.

jasonc65
quelle
1

Soweit ich weiß, impliziert jede Verkettung eine Speicherumverteilung. Das Problem ist also nicht der Operator, der dafür verwendet wird. Die Lösung besteht darin, die Anzahl der Verkettungen zu reduzieren. Führen Sie beispielsweise die Verkettungen außerhalb der Iterationsstrukturen durch, wenn Sie können.

David Ameller
quelle
Das ist eigentlich kein schlechter Rat, ich weiß nicht, warum er so abgelehnt wurde. Ich weiß, dass es die spezifische Frage nicht beantwortet, aber es verdient Anerkennung als allgemein guter Rat.
Augenlidlosigkeit
0

Ja, gemäß den üblichen Benchmarks. EG: http://mckoss.com/jscript/SpeedTrial.htm .

Für die kleinen Saiten ist dies jedoch irrelevant. Sie werden sich nur um Auftritte auf sehr großen Saiten kümmern. Darüber hinaus ist in den meisten JS-Skripten der Flaschenhals bei den String-Manipulationen selten, da nicht genug davon vorhanden ist.

Sie sollten die DOM-Manipulation besser beobachten.

e-satis
quelle
Der Link ist tot. Https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm verweist auf die Webarchivversion.
Tony