Załóżmy, że mam program do tworzenia ciągów w C #, który robi to:
StringBuilder sb = new StringBuilder();
string cat = "cat";
sb.Append("the ").Append(cat).(" in the hat");
string s = sb.ToString();
czy byłoby to tak wydajne czy bardziej wydajne, jak posiadanie:
string cat = "cat";
string s = String.Format("The {0} in the hat", cat);
Jeśli tak, dlaczego?
EDYTOWAĆ
Po kilku interesujących odpowiedziach zdałem sobie sprawę, że prawdopodobnie powinienem był trochę bardziej wyrazić, o co pytałem. Nie pytałem o to, co jest szybsze w konkatenacji ciągu, ale które jest szybsze w wstrzykiwaniu jednego ciągu do drugiego.
W obu powyższych przypadkach chcę wstrzyknąć jeden lub więcej ciągów w środek wstępnie zdefiniowanego ciągu szablonu.
Przepraszam za zamieszanie
string s = "The "+cat+" in the hat";
może być najszybszy, chyba że zostanie użyty w pętli, w którym to przypadku najszybszy będzie zStringBuilder
zainicjalizowanym poza pętlą.Odpowiedzi:
UWAGA: Ta odpowiedź została napisana, gdy bieżącą wersją był .NET 2.0. Może to już nie mieć zastosowania do późniejszych wersji.
String.Format
używaStringBuilder
wewnętrznie:Powyższy kod jest fragmentem z mscorlib, więc pytanie brzmi „jest
StringBuilder.Append()
szybsze niżStringBuilder.AppendFormat()
”?Bez testów porównawczych prawdopodobnie powiedziałbym, że powyższy przykład kodu działałby szybciej przy użyciu
.Append()
. Ale to przypuszczenie, spróbuj wykonać testy porównawcze i / lub profilowanie tych dwóch, aby uzyskać właściwe porównanie.Ten facet, Jerry Dixon, przeprowadził testy porównawcze:
Zaktualizowano:
Niestety powyższy link od tamtej pory umarł. Jednak wciąż jest kopia w Way Back Machine:
Ostatecznie zależy to od tego, czy formatowanie ciągu będzie wywoływane powtarzalnie, tj. Wykonujesz poważne przetwarzanie tekstu ponad 100 megabajtów tekstu, czy też jest wywoływane, gdy użytkownik od czasu do czasu klika przycisk. Jeśli nie wykonujesz jakiejś ogromnej pracy przetwarzania wsadowego, trzymałbym się String.Format, pomaga to w czytelności kodu. Jeśli podejrzewasz wąskie gardło perf, przyklej profiler do swojego kodu i zobacz, gdzie on naprawdę jest.
źródło
.ToString()
naStringBuilder
obiekcie. W wielu iteracjach ten czas robi wielką różnicę i oznacza, że nie porównuje on jabłek do jabłek. To jest powód, dla którego pokazuje tak świetne wynikiStringBuilder
i prawdopodobnie jest przyczyną jego zdziwienia. Właśnie powtarzane benchmark sprostowanie tego błędu i dostał Oczekiwane wyniki:String
+
operator był najszybszy, a następnieStringBuilder
, zString.Format
wychowywaniem tyłu.Z dokumentacji MSDN :
źródło
Przeprowadziłem kilka szybkich testów wydajności i dla 100 000 operacji uśrednionych w 10 przebiegach pierwsza metoda (String Builder) zajmuje prawie połowę czasu drugiej (String Format).
Więc jeśli jest to rzadkie, nie ma to znaczenia. Ale jeśli jest to typowa operacja, możesz użyć pierwszej metody.
źródło
Spodziewałbym się, że String.Format będzie wolniejszy - musi przeanalizować ciąg, a następnie go połączyć .
Kilka uwag:
źródło
Myślę, że w większości przypadków taka przejrzystość, a nie wydajność, powinna być Twoim największym zmartwieniem. Jeśli nie zmiażdżysz ton strun lub nie zbudujesz czegoś dla urządzenia mobilnego o niższej mocy, prawdopodobnie nie wpłynie to zbytnio na prędkość biegu.
Zauważyłem, że w przypadkach, w których buduję ciągi znaków w sposób dość liniowy, najlepszym rozwiązaniem jest wykonywanie prostych konkatenacji lub użycie StringBuilder. Sugeruję to w przypadkach, gdy większość tworzonego ciągu znaków jest dynamiczna. Ponieważ bardzo niewielka część tekstu jest statyczna, najważniejsze jest to, aby było jasne, gdzie jest umieszczany każdy fragment tekstu dynamicznego na wypadek, gdyby wymagał aktualizacji w przyszłości.
Z drugiej strony, jeśli mówisz o dużym kawałku statycznego tekstu z dwiema lub trzema zmiennymi, nawet jeśli jest to trochę mniej wydajne, myślę, że jasność, jaką zyskujesz dzięki łańcuchowi, jest tego warta. Użyłem tego na początku tego tygodnia, kiedy musiałem umieścić jeden bit dynamicznego tekstu w środku 4-stronicowego dokumentu. Łatwiej będzie zaktualizować ten duży fragment tekstu, jeśli jest on w jednym kawałku, niż aktualizować trzy elementy, które łączysz razem.
źródło
Choćby dlatego, że string.Format nie robi dokładnie tego, co myślisz, oto powtórka testów 6 lat później na Net45.
Concat jest nadal najszybszy, ale tak naprawdę to mniej niż 30% różnicy. StringBuilder i Format różnią się zaledwie o 5–10%. Kilka razy wykonałem testy w zakresie 20%.
Milisekundy, milion iteracji:
Lekcja, którą wyciągam, jest taka, że różnica w wydajności jest trywialna i nie powinna powstrzymywać Cię przed pisaniem najprostszego czytelnego kodu, jaki możesz. Co za moje pieniądze jest często, ale nie zawsze
a + b + c
.źródło
String.Format używa
StringBuilder
wewnętrznie ... tak logicznie, że prowadzi to do pomysłu, że byłby nieco mniej wydajny ze względu na większy narzut. Jednak prosta konkatenacja ciągów jest najszybszą metodą wstawienia jednego ciągu między dwa inne ... w znacznym stopniu. Ten dowód został przedstawiony przez Rico Mariani w jego pierwszym quizie wydajnościowym lata temu. Prosty fakt jest taki, że konkatenacje ... gdy znana jest liczba części struny (bez ograniczeń ... możesz połączyć tysiąc części ... o ile wiesz, że zawsze jest 1000 części) ... są zawsze szybsze niżStringBuilder
lub String. Format. Mogą być wykonywane z pojedynczą alokacją pamięci i serią kopii pamięci. Oto dowódA oto rzeczywisty kod niektórych metod String.Concat, które ostatecznie wywołują FillStringChecked, który używa wskaźników do kopiowania pamięci (wyodrębnianej przez Reflector):
A więc wtedy:
Cieszyć się!
źródło
Aha, najszybszy byłby:
źródło
StringBuilder
którą w pierwszej kolejności zoptymalizowano ten typ kodowania.To naprawdę zależy. W przypadku małych ciągów z kilkoma konkatenacjami w rzeczywistości szybciej jest po prostu dołączyć ciągi.
Ale w przypadku większych ciągów (bardzo bardzo dużych ciągów) bardziej wydajne jest użycie StringBuilder.
źródło
W takim przypadku sugerowałbym, aby String.Format był najszybszy, ponieważ został zaprojektowany w tym właśnie celu.
źródło
To naprawdę zależy od twojego wzorca użytkowania.
Szczegółowy test porównawczy między
string.Join
,string,Concat
istring.Format
można znaleźć tutaj: Ciąg.Format nie nadaje się do intensywnego rejestrowaniaźródło
Sugerowałbym, że nie, ponieważ String.Format nie był przeznaczony do konkatenacji, był przeznaczony do formatowania danych wyjściowych różnych danych wejściowych, takich jak data.
źródło