+ operatörü, StringBuffer.append () 'den daha az performanslıdır


91

Ekibimde, genellikle şu şekilde dizi birleştirme yaparız:

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

Açıkçası, aşağıdakiler çok daha okunabilir:

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

Ancak JS uzmanları, +operatörün performansından daha az performans gösterdiğini iddia ediyor StringBuffer.append(). Bu gerçekten doğru mu?


93
JavaScript'te StringBuffer yok
Tomas

7
Don, Java'dan mı bahsediyorsun?
James McMahon

Benim deneyimim, [].join('')gerçekten kablolu davranışlar göstermesiydi, bu yüzden +: - /
martyglaubitz

1
Buradaki temel sorunun dizgi birleştirme ile ilgili olduğunu biliyorum, ancak bunun gibi html öğeleri oluştururken dikkatli olmalısınız. urlÖrneğiniz 'veya içeriyorsa kırılabilir \n.
styfle

Yanıtlar:


46

Internet Explorer, günümüz dünyasında bundan gerçekten muzdarip olan tek tarayıcıdır. (5, 6 ve 7 sürümleri köpek yavaştır. 8 aynı bozulmayı göstermez.) Dahası, diziniz ne kadar uzun olursa IE yavaşlar ve yavaşlar.

Birleştirmeniz gereken uzun dizeleriniz varsa, kesinlikle bir array.join tekniği kullanın. (Veya okunabilirlik için bunun etrafında bir StringBuffer sarmalayıcısı.) Ama dizeleriniz kısaysa zahmet etmeyin.


102

Örneğiniz iyi bir örnek değil, çünkü performansın önemli ölçüde farklı olması pek olası değil. Örneğinizde okunabilirlik performansı gölgede bırakmalıdır çünkü birinin diğerine göre performans kazancı ihmal edilebilir. Bir dizinin (StringBuffer) faydaları yalnızca çok sayıda birleştirmeler yaptığınızda belirgindir. O zaman bile kilometreniz tarayıcınıza çok bağlı olabilir.

Burada, birçok farklı tarayıcıda tüm farklı JavaScript birleştirme yöntemlerini kullanarak performansı gösteren ayrıntılı bir performans analizi yer almaktadır; String Performansı ve Analizi

join () bir kez, concat () bir kez, join () for, + = for, concat () for

Daha fazla bilgi:
Ajaxian >> IE'de Dize Performansı: Array.join - + = devam ediyor


9
Grafikle ilgili olarak, açık olmaması durumunda; alçak daha iyi.
Teekin

1
"IE7 ile performans iyileştirmeleriyle ilgili ilk şeyler, artık büyük ölçekli dize işlemleri yaparken alternatif bir yol kullanmayı düşünmemize gerek yok; yinelemeli bir durumda Array.join kullanmak, aynı durumda + = kullanmaktan daha önemli bir avantaj sağlamaz. Ek olarak, IE6 ile olan farklılıklar, o belirli sürüm için çatallaşma zahmetine girmenize izin vermeyecek kadar küçüktü. "
Chris S

2
@Chris, bu doğru değil. Bu iki kemanlar karşılaştırın IE7 : jsfiddle.net/9uS4n/5 (hızlı) vs jsfiddle.net/9uS4n/2 (yavaş). join()Tekniği kullanarak performansta en az 1000 kat artış olduğu görülmektedir .
Kirk Woll

Güzel açıklama. Lütfen şunu da gözden geçirin
will824

37

Evet doğru ama aldırmamalısın. Okuması daha kolay olanla gidin. Uygulamanızı karşılaştırmanız gerekiyorsa, darboğazlara odaklanın.

Dize birleştirme işleminin darboğazınız olmayacağını tahmin ediyorum.


31

Michael Haren ile anlaştı .

Ayrıca dizilerin kullanımını düşünün ve performans gerçekten bir sorunsa birleştirin.

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

3
Doğru cevabın seçildiğini biliyorum ama bu cevabın daha faydalı bir örneği var.
Jason Sperske

1
Vay canına, sadece vay. Bu iki kemanlar karşılaştırın IE7 : jsfiddle.net/9uS4n/5 (hızlı) vs jsfiddle.net/9uS4n/2 (yavaş). Bu teknik kullanıldığında performansta en az 1000 kat artış olduğu görülmektedir.
Kirk Woll

@KirkWoll: Sonuçları kolayca karşılaştırabilmemiz için gelecekte jsPerf kullanmak isteyebilirsiniz .
rvighne

son zamanlarda bunu da yapıyorum, kod stili .NET StringBuilder'a benzer, var sb = []; sb.push ("bölüm 1"); sb.push ("bölüm 2"); dönüş sb.join ('');
Sam Jones

Bu jsPerf jsperf.com/join-concat/2 şu adreste bahsedilen: stackoverflow.com/questions/16696632/… bunun +=daha hızlı olduğunu gösteriyor gibi görünüyor .
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

18

Bunu dene:

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

Peki, cevabınızda bağlantı verdiğiniz gönderi, cevabımın önerdiği Array.join "efsanesini" özellikle çürütmeye çalışıyor. Yani belki de değil. Ben sadece pratikte daha hızlı olduğunu gördüklerimi yayınladım.
Rahul

bu string concat yöntemini seviyorum.
bkwdesign

8

Zaten bazı kullanıcıların belirttiği gibi: Bu, küçük dizeler için önemsizdir.

Firefox, Safari veya Google Chrome'daki yeni JavaScript motorları,

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

kadar hızlı

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

8

JavaScript'in yerel bir StringBuffer nesnesi yok, bu yüzden bunun kullandığınız bir kitaplıktan veya sıra dışı bir ana bilgisayar ortamının bir özelliğinden (yani tarayıcı değil) olduğunu varsayıyorum.

Yerel bir StringBuffer nesnesi yapabilse de, bir kütüphanenin (JS'de yazılmış) daha hızlı bir şey üreteceğinden şüpheliyim. Kesin cevap bir profil oluşturucu ile bulunabilir (bir tarayıcıda çalıştırıyorsanız, Firebug size Firefox'ta bulunan JS motoru için bir profil oluşturucu sağlayacaktır).


6

Knuth'un sözleriyle, "erken optimizasyon tüm kötülüklerin köküdür!" Her iki şekilde de küçük defansın sonunda büyük olasılıkla pek bir etkisi olmayacaktır; Daha okunaklı olanı seçerdim.


1
Geleneksel olarak StringBuffer, birleştirme yerine kullanılır çünkü birincisi O (N) zaman karmaşıklığına sahipken, ikincisi O (N ^ 2) olarak zaman karmaşıklığına sahiptir, bu nedenle fark büyük N için önemlidir (ancak küçük N için değil). Her durumda, O (N ^ 2) senaryosu, kullanılan ortama bağlı olarak JavaScript'te geçerli olmayabilir.
redcalx

4

Okunması daha kolay yöntem, koda bakarken insanlara algılanabilir miktarda zaman kazandırırken, "daha hızlı" yöntem yalnızca insanlar sayfaya göz atarken fark edilemeyecek ve muhtemelen ihmal edilebilir miktarlarda zaman harcıyor.

Bu gönderinin kötü olduğunu biliyorum, ancak yanlışlıkla bunun farklı bir konu olduğunu düşünerek tamamen farklı bir şey gönderdim ve gönderileri nasıl sileceğimi bilmiyorum. Benim hatam...


3

Hızlı bir kıyaslama oluşturmak ve jspref.com'u kullanarak Javascript performans varyasyonlarına göz atmak oldukça kolaydır . Muhtemelen bu soru sorulduğunda ortalıkta yoktu. Ancak bu soruya tökezleyen insanlar için siteye bir göz atmaları gerekir.

Ben de birleştirme çeşitli yöntemlerin hızlı bir test yaptım http://jsperf.com/string-concat-methods-test .


Buna bakılırsa, bugünlerde + operatörü ile birleştirme kesinlikle gidilecek yol gibi görünüyor. Yanlış okumadıysam. Bu tamamen mantıklı.
Richard

2

İşlevsel stili kullanmayı seviyorum, örneğin:

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

Bu stil okunabilir ve şeffaf görünüyor. Kodda tekrarlamayı azaltan yardımcı programların oluşturulmasına yol açar.

Bu ayrıca ara dizeleri otomatik olarak kullanma eğilimindedir.


1

Bildiğim kadarıyla, her birleştirme, bir bellek yeniden tahsisi anlamına gelir. Yani sorun, bunu yapmak için kullanılan operatör değil, çözüm, birleştirme sayısını azaltmaktır. Örneğin, birleştirme işlemlerini yapabildiğiniz zaman yineleme yapılarının dışında yapın.


Bu aslında kötü bir tavsiye değil, neden bu kadar reddedildiğini bilmiyorum. Belirli bir soruyu yanıtlamadığını biliyorum, ancak genel olarak iyi bir tavsiye olarak tanınmayı hak ediyor.
eyelidlessness

0

Evet, olağan ölçütlere göre. Örneğin: http://mckoss.com/jscript/SpeedTrial.htm .

Ancak küçük dizeler için bu önemsizdir. Sadece çok büyük dizelerdeki performansları önemseyeceksiniz. Dahası, çoğu JS betiğinde, şişe boynu, yeterince olmadığı için nadiren dize manipülasyonlarında bulunur.

DOM manipülasyonunu izlemelisiniz.


Bağlantı öldü .. https://web.archive.org/web/20150912072015/http://mckoss.com/jscript/SpeedTrial.htm web arşivi sürümünü gösteriyor.
Tony
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.