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

Как работает StringBuilder?

Как работает StringBuilder?

Что он делает внутри? Использует ли он небезопасный код? И почему это так быстро (по сравнению с оператором +)?

4b9b3361

Ответ 1

Когда вы используете оператор + для создания строки:

string s = "01";
s += "02";
s += "03";
s += "04";

то при первом конкатенации мы создаем новую строку длиной четыре и копируем "01" и "02" в нее - копируются четыре символа. На втором конкатенации мы создаем новую строку длиной шесть и копируем в нее "0102" и "03" - копируются шесть символов. На третьем concat мы создаем строку длиной восемь и копируем в нее "010203" и "04" - копируем восемь символов. До сих пор для этой восьмисимвольной строки было скопировано в общей сложности 4 + 6 + 8 = 18 символов. Продолжайте.

...
s += "99";

На 98-м concat мы делаем строку длиной 198 и копируем в нее "010203... 98" и "99". Это дает нам в общей сложности 4 + 6 + 8 +... + 198 = много, чтобы сделать эту строку символов 198.

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

Что происходит, когда предположение неверно и массив заполняется? Есть две стратегии. В предыдущей версии структуры построитель строк перераспределял и копировал массив, когда он был заполнен, и удваивал его размер. В новой реализации строковый построитель поддерживает связанный список относительно небольших массивов и добавляет новый массив в конец списка, когда старый заполняется.

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

Ответ 2

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

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

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

Для получения дополнительной информации см. мою статью о StringBuilder.

Ответ 4

Microsoft CLR выполняет некоторые операции с внутренним вызовом (не совсем как небезопасный код). Наибольшее преимущество в производительности по сравнению с конкатенированными строками + заключается в том, что он записывает в char[] и не создает столько промежуточных строк. Когда вы вызываете ToString(), он строит завершенную неизменяемую строку из вашего содержимого.

Ответ 5

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

Поскольку StringBuilder может изменять строковый буфер, ему не нужно создавать новое строковое значение для каждого изменения строковых данных. Когда вы используете оператор +, компилятор превращает это в вызов String.Concat, который создает новый строковый объект. Этот, казалось бы, невинный фрагмент кода:

str += ",";

заключается в следующем:

str = String.Concat(str, ",");