String vs. StringBuilder - PullRequest
       106

String vs. StringBuilder

201 голосов
/ 16 сентября 2008

Я понимаю разницу между String и StringBuilder (StringBuilder изменяемый), но есть ли большая разница в производительности между ними?

В программе, над которой я работаю, добавлено много строк (500+). Является ли использование StringBuilder лучшим выбором?

Ответы [ 24 ]

223 голосов
/ 16 сентября 2008

Да, разница в производительности значительна. См. Статью базы знаний " Как улучшить производительность конкатенации строк в Visual C # ".

Я всегда пытался сначала написать код для ясности, а потом оптимизировать производительность. Это намного проще, чем делать это наоборот! Однако, увидев огромную разницу в производительности в моих приложениях между этими двумя, я теперь думаю об этом немного более тщательно.

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

54 голосов
/ 16 сентября 2008

Чтобы уточнить, что сказала Джиллиан о 4-х струнах, если у вас есть что-то вроде этого:

string a,b,c,d;
 a = b + c + d;

тогда было бы быстрее использовать строки и оператор плюс. Это потому, что (подобно Java, как указывает Эрик), он автоматически использует StringBuilder (на самом деле он использует примитив, который также использует StringBuilder)

Однако, если то, что вы делаете, ближе к:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

Тогда вам нужно явно использовать StringBuilder. .Net здесь не создает автоматически StringBuilder, потому что это было бы бессмысленно. В конце каждой строки «a» должна быть (неизменяемой) строкой, поэтому она должна создавать и размещать StringBuilder в каждой строке. Для скорости вам нужно будет использовать тот же StringBuilder, пока вы не закончите сборку:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();
28 голосов
/ 16 сентября 2008

StringBuilder предпочтительнее ЕСЛИ вы делаете несколько циклов или разветвлений при передаче кода ... однако, для производительности PURE, если вы можете обойтись без SINGLE объявления строки тогда это намного более производительно.

Например:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

более производительный, чем

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

В этом случае StringBuild можно считать более поддерживаемым, но не более производительным, чем однострочное объявление.

9 раз из 10, хотя ... используйте построитель строк.

С другой стороны: строка + var также более производительна, чем строка. Подход форматирования (обычно), который использует StringBuilder для внутреннего использования (в случае сомнений ... проверьте отражатель!)

23 голосов
/ 16 сентября 2008

Этот тест показывает, что обычная конкатенация быстрее при объединении 3 или менее строк.

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

StringBuilder может значительно улучшить использование памяти, особенно в случае добавления 500 строк вместе.

Рассмотрим следующий пример:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

Что происходит в памяти? Создаются следующие строки:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

Добавив эти пять чисел в конец строки, мы создали 13 строковых объектов! И 12 из них были бесполезны! Ничего себе!

StringBuilder решает эту проблему. Это не «изменяемая строка», как мы часто слышим ( все строки в .NET неизменны ). Он работает, сохраняя внутренний буфер, массив char. Вызов Append () или AppendLine () добавляет строку в пустое пространство в конце массива char; если массив слишком мал, он создает новый, больший массив и копирует туда буфер. Таким образом, в приведенном выше примере StringBuilder может потребоваться только один массив, содержащий все 5 дополнений к строке - в зависимости от размера его буфера. Вы можете указать StringBuilder, насколько большим должен быть его буфер в конструкторе.

19 голосов
/ 30 июля 2013

Простой пример демонстрации разницы в скорости при использовании String конкатенации против StringBuilder:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

Результат:

Использование конкатенации строк: 15423 миллисекунды

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

Результат:

Использование StringBuilder: 10 миллисекунд

В результате первая итерация заняла 15423 мс, а вторая итерация с использованием StringBuilder заняла 10 мс.

Мне кажется, что использование StringBuilder быстрее, намного быстрее.

11 голосов
/ 26 февраля 2015

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

.

String Vs Stringbuilder

  • String

    1. под System пространством имен
    2. неизменяемый (только для чтения) экземпляр
    3. производительность ухудшается при постоянном изменении значения
    4. потокобезопасный
  • StringBuilder (изменяемая строка)

    1. под System.Text пространством имен
    2. изменяемый экземпляр
    3. показывает лучшую производительность, поскольку в существующий экземпляр внесены новые изменения

Настоятельно рекомендую статью для моба dotnet: String Vs StringBuilder в C # .

Вопрос, связанный с переполнением стека: Изменчивость строки в строке не меняется в C #? .

8 голосов
/ 16 сентября 2008

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

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

против

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once
4 голосов
/ 15 декабря 2018

String Vs String Builder:

Прежде всего вы должны знать, в каком собрании живут эти два класса?

Итак,

строка присутствует в System пространстве имен.

и

StringBuilder присутствует в пространстве имен System.Text.

Для строка объявление:

Вы должны включить пространство имен System. что-то вроде этого. Using System;

и

Для StringBuilder Объявление:

Вы должны включить пространство имен System.text. что-то вроде этого. Using System.text;

Теперь наступит актуальный вопрос.

В чем разница между string & StringBuilder ?

Основное различие между этими двумя заключается в том, что:

строка является неизменной.

и

StringBuilder является изменяемым.

Итак, давайте теперь обсудим разницу между неизменным и изменяемым

Изменяемый: : означает изменяемый.

Неизменный: : означает, что невозможно изменить.

Например:

using System;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // String Example

            string name = "Rehan";
            name = name + "Shah";
            name = name + "RS";
            name = name + "---";
            name = name + "I love to write programs.";

            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah RS --- I love to write programs."
        }
    }
}

Так что в этом случае мы собираемся изменить один и тот же объект 5 раз.

Итак, очевидный вопрос таков! Что на самом деле происходит под капотом, когда мы меняем одну и ту же строку 5 раз.

Вот что происходит, когда мы меняем одну и ту же строку 5 раз.

давай посмотрим на рисунок.

enter image description here

Explaination:

Когда мы впервые инициализируем эту переменную "name" в "Rehan" i-e string name = "Rehan" эта переменная создается в стеке "name" и указывает на это значение "Rehan". после выполнения этой строки: "name = name +" Shah ". Переменная-ссылка больше не указывает на этот объект" Rehan ", теперь она указывает на" Shah "и т. д.

Таким образом, string является неизменным, что означает, что как только мы создаем объект в памяти, мы не можем его изменить.

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

Итак, из вышеприведенного рисунка у нас есть пять объектов, четыре объекта выброшены, они вообще не используются. Они все еще остаются в памяти, и они занимают объем памяти. «Сборщик мусора» отвечает за то, что так убирает ресурсы из памяти.

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

Итак, это история строковой переменной.

Теперь давайте посмотрим на объект StringBuilder. Например:

using System;
using System.Text;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // StringBuilder Example

            StringBuilder name = new StringBuilder();
            name.Append("Rehan");
            name.Append("Shah");
            name.Append("RS");
            name.Append("---");
            name.Append("I love to write programs.");


            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah Rs --- I love to write programs."
        }
    }
}

Так что в этом случае мы собираемся изменить один и тот же объект 5 раз.

Итак, очевидный вопрос таков! Что на самом деле происходит под капотом, когда мы меняем один и тот же StringBuilder 5 раз.

Вот что происходит, когда мы меняем один и тот же StringBuilder 5 раз.

давай посмотрим на фигуру. enter image description here

Explaination: В случае объекта StringBuilder. Вы не получите новый объект. Тот же объект будет изменен в памяти, поэтому даже если вы измените объект и, скажем, 10000 раз, у нас останется только один объект stringBuilder.

У вас нет большого количества мусорных объектов или не-связанных объектов stringBuilder, потому что это может быть изменено. Это изменчивое значение, что оно меняется со временем?

Отличия:

  • String присутствует в пространстве имен System, где присутствует Stringbuilder в пространстве имен System.Text.
  • Строка неизменна, так как StringBuilder имеет значение mutabe.
4 голосов
/ 26 октября 2010

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

Источник: MSDN

3 голосов
/ 17 сентября 2008

StringBuilder лучше для построения строки из множества непостоянных значений.

Если вы строите строку из большого количества постоянных значений, таких как несколько строк значений в документе HTML или XML или других кусках текста, вы можете просто добавить одну и ту же строку, потому что почти все компиляторы выполняют «постоянное сворачивание», процесс сокращения дерева разбора, когда у вас есть куча постоянных манипуляций (это также используется, когда вы пишете что-то вроде int minutesPerYear = 24 * 365 * 60). А для простых случаев с непостоянными значениями, добавляемыми друг к другу, компилятор .NET уменьшит ваш код до чего-то похожего на то, что делает StringBuilder.

Но когда ваше дополнение не может быть уменьшено компилятором до чего-то более простого, вам понадобится StringBuilder. Как указывает fizch, это скорее всего произойдет внутри цикла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...