Подтвердить что ты не робот

В какой момент использование StringBuilder становится незначительным или накладными?

Недавно я обнаружил, что использую StringBuilder для всех конкатенаций строк, больших и малых, однако в недавнем тесте производительности я заменил строку коллегиOut = string1 + "." string2 style concatenation (используется в цикле 10000x + с StringBuilder, который каждый раз новичок) для StringBuilder просто для того, чтобы увидеть, какая разница в незначительной конкатенации.

Я обнаружил, что во многих прогонах теста производительности изменение было незначительно выше или ниже независимо от конкатенации или StringBuilder (повторение этого было для небольших конкатенаций).

В какой момент "новичка" объекта StringBuilder отрицает преимущества использования одного?

4b9b3361

Ответ 1

Следующее правило -

Используйте StringBuilder, когда количество конкатенаций неизвестно во время компиляции.

Итак, в вашем случае каждый StringBuilder добавлялся только несколько раз, а затем был отброшен. Это не похоже на что-то вроде

string s = String.Empty;
for (int i = 0; i < 10000; ++i)
{
    s += "A";
}

Если использование StringBuilder резко улучшит производительность, потому что в противном случае вы постоянно выделяете новую память.

Ответ 2

Уверен, у меня есть другой ответ, когда я опубликовал ссылку на мою статью, а затем ее резюме, но здесь мы идем еще раз.

  • Определенно используйте StringBuilder, когда вы объединяетесь в нетривиальный цикл - особенно если вы не знаете точно (во время компиляции), сколько итераций вы совершите через цикл. Например, чтение файла персонажем за раз, создание строки при использовании с помощью оператора + = потенциально может привести к самоубийству.

  • Определенно используйте оператор конкатенации, когда вы можете (читаемо) указать все, что необходимо объединить в одном из утверждений. (Если у вас есть массив вещей для конкатенации, подумайте о вызове String.Concat явно - или String.Join, если вам нужен разделитель.)

  • Не бойтесь разбить литералы на несколько конкатенированных бит - результат будет таким же. Вы можете облегчить чтение, разбив длинный литерал на несколько строк, например, без ущерба для производительности.

  • Если вам нужны промежуточные результаты конкатенации для чего-то другого, кроме подачи следующей итерации конкатенации, StringBuilder не поможет вам. Например, если вы создадите полное имя от имени и фамилии, а затем добавите третью часть информации (возможно, прозвище) до конца, вам будет полезно использовать StringBuilder, если вы 't нужна строка (имя и фамилия + имя) для других целей (как в примере, который создает объект Person).

  • Если у вас всего несколько конкатенаций, и вы действительно хотите сделать их в отдельных заявлениях, не имеет значения, в каком направлении вы идете. Какой способ более эффективен, будет зависеть от количества конкатенаций, связанных с размером строки, и от того, в каком порядке они объединены. Если вы действительно считаете, что часть кода является узким местом производительности, профилем или эталоном в обоих направлениях.

Ответ 3

Иногда стоит посмотреть документацию:

Производительность конкатенации операции для строки или Объект StringBuilder зависит от того, как часто происходит выделение памяти. Операция конкатенации строк всегда выделяет память, тогда как Операция конкатенации StringBuilder выделяет только память, если Буфер объекта StringBuilder тоже небольшой для размещения новых данных. Следовательно, класс String предпочтительнее для конкатенации если фиксированное число String объекты объединены. В этом случай, индивидуальная конкатенация операции могут быть даже объединены в одна операция компилятором. Объект StringBuilder предпочтительнее для операцию конкатенации, если произвольное число строк сцеплены; например, если цикл объединяет случайное число строки ввода пользователя.

В вашем примере есть только одна конкатенация на выходную строку, поэтому StringBuilder ничего не получает. Вы должны использовать StringBuilder в случаях, когда вы добавляете одну и ту же строку много раз, например:

stringOut = ...
for(...)
    stringOut += "."
    stringOut += string2

Ответ 4

Мое эмпирическое правило прост.

  • Если вы разумно можете написать одно выражение, которое создает окончательное, используйте +.
  • Если вы не можете (из-за размера или изменчивости), используйте StringBuilder.

По моему опыту, выражения, такие как:

"Id: " + item.id + " name: " + item.name

может быть написано и понято гораздо легче, чем:

StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(item.id);
sb.append(" name: ").append(item.name);

(за которым следует строка из sb, где было написано вышеприведенное выражение), и она работает одинаково хорошо (подсказка: посмотрите на скомпилированный код, чтобы узнать, почему!)

С другой стороны, когда необходимо накопить строку с течением времени (по мере запуска программы) или пространство (состоящее из значений, поступающих из разных частей кода), таким образом, что нецелесообразно писать в виде одного -line, то StringBuilder избегает накладных расходов (время и память):

String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...

Ответ 5

От MSDN:

[T] класс String предпочтительнее для операция конкатенации, если фиксированная количество объектов String сцепляются. В этом случае индивидуальные операции конкатенации может быть даже объединена в единую работа компилятора. Объект StringBuilder предпочтительнее для операцию конкатенации, если произвольное число строк сцеплены; например, если цикл объединяет случайное число строки ввода пользователя.

Я думаю, что ответ "зависит" - если вы конкатенируете внутри цикла с более чем несколькими итерациями, то StringBuilder почти всегда будет обеспечивать лучшую производительность, но единственный способ узнать наверняка - это фактически профиль.

Ответ 6

Там интересная статья об этом в Coding Horror. Джефф получил следующие результаты за 100 000 итераций на двухъядерном 3,5 ГГц Core 2 Duo:

 Simple Concatenation    - 606 ms
 String.Format           - 665 ms
 string.Concat           - 587 ms
 String.Replace          - 979 ms
 StringBuilder           - 588 ms

Ответ 7

От Dot Net Perls:

Когда использовать StringBuilder?

StringBuilder полностью оптимизирован и не предлагает никаких логических улучшений для строки Concat, отличной от внутренней реализации. Тем не менее, очень важно правильно использовать его в высокопроизводительных приложениях и веб-сайтах.

Иногда, можно использовать небольшие циклы с 4 или менее итерациями с простой строкой Concats. Однако в случае краев это может быть катастрофическим. Планируйте свои граничные случаи с помощью StringBuilder.