Строка против StringBuilder

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

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

Ответ 1

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

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

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

Ответ 2

Чтобы выяснить, что сказала Гиллиан о 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();

Ответ 3

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 также более эффективна, чем метод string.Format(обычно), который использует StringBuilder внутри (если есть сомнения... проверьте отражатель!)

Ответ 4

Этот тест показывает, что регулярная конкатенация выполняется быстрее при объединении 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 из них бесполезны! Wow!

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

Ответ 5

Простой пример, чтобы продемонстрировать разницу в скорости при использовании 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 быстрее, намного быстрее.

Ответ 7

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

String Vs Stringbuilder

  • String

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

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

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

Связанный вопрос: изменчивость строки, когда строка не изменяется в С#? ,

Ответ 8

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

Ответ 9

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

Источник: MSDN

Ответ 10

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

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

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

Ответ 11

String Vs String Builder:

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

Так,

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

а также

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

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

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

а также

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

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

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

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

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

Строка неизменна.

а также

StringBuilder изменчив.

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

Mutable: средство изменчива.

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

Например:

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", т.е. 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

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

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

Отличия:

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

Ответ 12

Я считаю, что StringBuilder быстрее, если у вас есть более 4 строк, которые нужно добавить вместе. Кроме того, он может делать некоторые интересные вещи, такие как AppendLine.

Ответ 13

В .NET StringBuilder все еще быстрее, чем добавляя строки. Я уверен, что в Java они просто создают StringBuffer под капотом, когда вы добавляете строки, поэтому на самом деле нет разницы. Я не уверен, почему они еще не сделали этого в .NET.

Ответ 14

Использование строк для конкатенации может привести к сложности выполнения в размере O(n^2).

Если вы используете StringBuilder, копирование памяти происходит намного меньше, что нужно сделать. С помощью StringBuilder(int capacity) вы можете увеличить производительность, если сможете оценить, насколько велика будет финальная String. Даже если вы не точны, вам, вероятно, придется увеличить емкость StringBuilder пару раз, что также может помочь в производительности.

Ответ 15

Я видел значительный прирост производительности при использовании вызова метода EnsureCapacity(int capacity) в экземпляре StringBuilder перед его использованием для любого хранилища строк. Обычно я называю это в строке кода после создания экземпляра. Он имеет такой же эффект, как если бы вы создавали экземпляр StringBuilder следующим образом:

var sb = new StringBuilder(int capacity);

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

Ответ 17

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

IMHO, добавив 500+ строковых записей, обязательно должен использовать StringBuilder.

Ответ 18

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

например.

StringBuilder sb = new StringBuilder (50);

Ответ 19

Конкатенация строк будет стоить вам больше. В Java вы можете использовать StringBuffer или StringBuilder на основе ваших потребностей. Если вам нужна синхронизированная и потокобезопасная реализация, перейдите к StringBuffer. Это будет быстрее, чем конкатенация строк.

Если вам не нужна синхронизированная или потоковая реализация, перейдите к StringBuilder. Это будет быстрее, чем String concatenation, а также быстрее, чем StringBuffer, поскольку они не являются служебными данными синхронизации.

Ответ 20

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

Ответ 21

Если вы выполняете много конкатенации строк, используйте StringBuilder. Когда вы объединяетесь со строкой, вы каждый раз создаете новую строку, используя больше памяти.

Алекс

Ответ 23

Как правило, если мне нужно установить значение строки более одного раза или если есть какие-либо добавления к строке, тогда это должен быть построитель строк. Я видел приложения, которые я написал в прошлом, прежде чем узнавать о строковых сборщиках, у которых был огромный отпечаток памяти, который, как кажется, продолжает расти и расти. Изменение этих программ на использование построителя строк значительно сократило использование памяти. Теперь я клянусь строчным построителем.

Ответ 24

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

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

Как вы можете видеть, 200 000 итераций заняли 22 секунды, а 1 миллион итераций с использованием StringBuilder было почти мгновенным.

string s = string.Empty;
StringBuilder sb = new StringBuilder();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 50000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 200000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());

for (int i = 0; i <= 1000000; i++)
{
    sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());

Console.ReadLine();

Результат приведенного выше кода:

Начало строки + 28/01/2013 16:55:40.

Готовая строка + 28/01/2013 16:55:40.

Начало строки + 28/01/2013 16:55:40.

Законченная строка + 28/01/2013 16:56:02.

Начало Sb добавлено 28/01/2013 16:56:02.

Готово Sb добавлено 28/01/2013 16:56:02.

Ответ 25

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