Я изучал вопрос, который мне был представлен: как написать функцию, которая берет строку в качестве ввода и возвращает строку с пробелами между символами. Функция должна быть написана для оптимизации производительности, когда она называется тысячами раз в секунду.
-
Я знаю, что .net имеет функцию под названием
String.Join, к которой я могу передать символ пробела в качестве разделителя вместе с исходной строкой. -
Запрет использования
String.Join, я могу использовать классStringBuilderдля добавления пробелов после каждого символа. -
Другой способ выполнить эту задачу - объявить массив символов с 2 * n-1 символами (вы должны добавить n-1 символов для пробелов). Массив символов может быть заполнен в цикле, а затем передан в строку
constructor.
Я написал некоторый .net-код, который запускает каждый из этих алгоритмов один миллион раз каждый с параметром "Hello, World" и измеряет, сколько времени требуется для его выполнения. Метод (3) намного, намного быстрее, чем (1) или (2).
Я знаю, что (3) должен быть очень быстрым, потому что он избегает создания каких-либо дополнительных ссылок на строки для сбора мусора, но мне кажется, что встроенная функция .net, такая как String.Join, должна обеспечивать хорошую производительность. Почему использование String.Join намного медленнее, чем выполнение работы вручную?
public static class TestClass
{
// 491 milliseconds for 1 million iterations
public static string Space1(string s)
{
return string.Join(" ", s.AsEnumerable());
}
//190 milliseconds for 1 million iterations
public static string Space2(string s)
{
if (s.Length < 2)
return s;
StringBuilder sb = new StringBuilder();
sb.Append(s[0]);
for (int i = 1; i < s.Length; i++)
{
sb.Append(' ');
sb.Append(s[i]);
}
return sb.ToString();
}
// 50 milliseconds for 1 million iterations
public static string Space3(string s)
{
if (s.Length < 2)
return s;
char[] array = new char[s.Length * 2 - 1];
array[0] = s[0];
for (int i = 1; i < s.Length; i++)
{
array[2*i-1] = ' ';
array[2*i] = s[i];
}
return new string(array);
}
Обновление: Я изменил свой проект на режим "Отпуск" и обновил мои прошедшие времена в вопросе соответственно.