Страницы

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

понедельник, 8 июля 2019 г.

C# и .NET. Какой метод будет менее ресурсозатратный и какой будет быстрее выполняться?

Добрый день! Я новичок в .NET и я задался вопросом (вопрос чисто на интерес и не имеет никакой практической цели): Какой из методов для вывода массива лучше использовать:
Который будет в цикле на каждый элемент вызывать метод Console.Write($"{element} ") Который будет использовать класс StringBuilder и вызывать в цикле на каждой итерации метод Append(element) и Append(' ') и в конце вызовет 1 метод Console.WriteLine();
P.S. Проблемы с созданием списка в вопросе. Вроде как делаю все по инструкции, а список не создается.
UPD. Методы, про которые я говорю:
Метод 1
private static void PrintArray(T[] Array) { foreach (T item in Array) { Console.Write($"{item} "); }
Console.WriteLine(); }
Метод 2
private static void PrintArray(T[] Array) { StringBuilder stringBuilder = new StringBuilder();
foreach (T item in Array) { stringBuilder.Append(item); stringBuilder.Append(' '); }
Console.WriteLine(stringBuilder.ToString()); }


Ответ

Хм... Со StringBuilder получается 36 МС, а без него 523 МС.
Вот код для тестирования:
static void Main(string[] args) { const int len = 1000; //Размер массива string[] arr = new string[len]; for (int i = 0; i < arr.Length; i++) { arr[i] = "blablablabla"; } StringBuilder strBuilder = new StringBuilder(); int counter = 0; var stopWatch1 = new Stopwatch(); stopWatch1.Start(); for (int i = 0; i < arr.Length ; i++) { if (counter>=100|| i== arr.Length - 1) //Пуляем по 100 элементов в консоль { Console.Write(strBuilder.ToString()); strBuilder.Clear(); counter = 0; } counter++; strBuilder.Append("
" + arr[i]); } stopWatch1.Stop(); var stopWatch2 = new Stopwatch(); stopWatch2.Start(); for (int i = 0; i < arr.Length; i++) { Console.WriteLine(arr[i]); } stopWatch2.Stop(); Console.WriteLine($"StringBuilder MS={stopWatch1.ElapsedMilliseconds}"); Console.WriteLine($"Без StringBuilder MS={stopWatch2.ElapsedMilliseconds}"); Console.ReadKey(); } }
Однако, не стоит пытаться все подряд оптимизировать и оптимизацией следует заниматься только в том случае, если это критическая точка программы.
Есть знаменитая фраза:
Преждевременная оптимизация — корень всех зол

В комментария меня поправили и на самом деле автору хотелось выводить строку не порциями, как я тестировал, а агрегировать ее в StringBuilder, а потом за один раз вывести.
В этом случае первый цикл будет таким:
for (int i = 0; i < arr.Length ; i++) { strBuilder.Append("
" + arr[i]); } Console.Write(strBuilder.ToString());
В итоге скорость на 1000 элемента изменилась с 36 МС до ~20 МС.
Но нужно иметь в виду, что консоль не бесконечная и если я не ошибаюсь, то одновременно в них может находится ~8000 символов => пытаясь вывести за раз большее количество, мы теряем часть информации => вывод порциями более правильный.
Так же побочный эффект этого подхода в том, что объединенный массив где-то нужно хранить=> большие расходы на память, если массив здоровенный.
Разница во времени с использованием StringBuilder и без его использования я думаю, что можно объяснить тем, что операция IO сама по себе медленная=> чем реже мы обращаемся к консоли, тем быстрее работает все в целом.

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

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