Страницы

Поиск по вопросам

понедельник, 29 октября 2018 г.

StringBuilder vs. String.Concat, C# [дубликат]

На данный вопрос уже ответили: Быстродействие объединения строк 1 ответ Update: Мои тесты были неправильные. StringBuilder выигрывает даже при объединении 5 строк
Я сравнил производительность StringBuilder и String.Concat c разным количеством строк, учитывая время на создание объекта StringBuilder.
При объединении 5 строк String.Concat всегда быстрее, иногда в 10 раз
При объедении 10 строк String.Concat всегда быстрее, иногда в 10 раз
При объединении 20 строк String.Concat всегда быстрее, иногда в 10 раз
Если ли смысл использовать StringBuilder для объединения маленького количества строк? Вроде объект StringBuilder сам по себе отнимает больше ресурсов, чем 20 строк.
Код, который использовался для теста:
class Program { static void Main(string[] args) { const int countOfStrings = 20; string[] stringsToMerge = new string[countOfStrings];
for (int i = 0; i < countOfStrings; i++) { stringsToMerge[i] = "stringN" + i; }
Console.WriteLine("Count of strings:" + countOfStrings);
Stopwatch stopWatch = new Stopwatch(); TimeSpan ts; stopWatch.Start(); stopWatch.Stop();
stopWatch.Restart(); string s = stringsToMerge[0]; for (int i = 1; i < countOfStrings; i++) { s = string.Concat(s, stringsToMerge[i]); } stopWatch.Stop(); ts = stopWatch.Elapsed; Console.WriteLine("String.Concat ms:" + ts.TotalMilliseconds);
stopWatch.Restart(); StringBuilder stringBuilder = new StringBuilder(stringsToMerge[0]); for (int i = 1; i < countOfStrings; i++) { stringBuilder.Append(stringsToMerge[i]); } stopWatch.Stop(); ts = stopWatch.Elapsed; Console.WriteLine("StringBuilder ms:" + ts.TotalMilliseconds);
Console.ReadKey();
} }


Ответ

Я исправил ваш код. Во-первых, перед тестированием скорости, все методы нужно "прогреть". При первом вызове JIT-компилятор генерирует машинный код с IL и это занимает некоторое время. Во-вторых, не нужно тестировать одну итерацию, так как случайное событие в ОС может исказить результат. Во-третьих, вы передаете странное значение, в конструктор StringBuilder. При его использовании заведомо создается маленький размер буфера, который будет расширяться несколько раз. Для максимальной производительности, если есть возможность, вы должны задавать размер буфера, который не будет менятся.
И не забывайте запускать в Release, а не в Debug
В исправленном варианте (не трогал конструктор):
Count of strings:5 String.Concat ms:1097.4772 StringBuilder ms:1294.881
Count of strings:10 String.Concat ms:2848.4845 StringBuilder ms:1970.4477
Уже на 10 выигрывает StringBuilder
const int countOfStrings = 5; const int iterations = 10000000; string[] stringsToMerge = new string[countOfStrings];
for (int i = 0; i < countOfStrings; i++) { stringsToMerge[i] = "stringN" + i; }
// компилируем IL в машинный код string.Concat("123", "qwe"); var x = new StringBuilder(40); x.Append("123qwe");
Console.WriteLine("Count of strings:" + countOfStrings);
Stopwatch stopWatch = new Stopwatch(); TimeSpan ts; stopWatch.Start(); stopWatch.Stop();
stopWatch.Restart(); for (int iter = 0; iter < iterations; iter++) { string s = stringsToMerge[0]; for (int i = 1; i < countOfStrings; i++) { s = string.Concat(s, stringsToMerge[i]); } } stopWatch.Stop(); ts = stopWatch.Elapsed; Console.WriteLine("String.Concat ms:" + ts.TotalMilliseconds);
stopWatch.Restart(); for (int iter = 0; iter < iterations; iter++) { StringBuilder stringBuilder = new StringBuilder(stringsToMerge[0]); for (int i = 1; i < countOfStrings; i++) { stringBuilder.Append(stringsToMerge[i]); } } stopWatch.Stop(); ts = stopWatch.Elapsed; Console.WriteLine("StringBuilder ms:" + ts.TotalMilliseconds);
Если же я переделаю использование StringBuilder, то он выигрывает уже на 5 строках:
StringBuilder stringBuilder = new StringBuilder(100); for (int i = 0; i < countOfStrings; i++) { stringBuilder.Append(stringsToMerge[i]); }
Count of strings:5 String.Concat ms:1053.0082 StringBuilder ms:699.7725

Комментариев нет:

Отправить комментарий