В настоящее время я работаю над чем-то, что требует иерархии, такой как дизайн (примерно так же, как в unity ... На самом деле, я просто делаю копию единства на вершине единства как опыт обучения), что требует много вставки/перемещения объектов внутри списка. По этой причине я решил пойти с LinkedList для хранения всех объектов иерархии (первый раз, когда я когда-либо пользовался списком ListList).Iterating LinkedListed Performance C#
Я решил посмотреть, какой метод петли над связанным списком был наиболее эффективным. Я знаю, что я, вероятно, оптимизирую микро, но я вообще изучаю новые вещи, тестируя материал, и результаты моего теста удивили меня совсем немного, поэтому я надеялся, что кто-то сможет пролить свет на него.
(я не специалист по настройке тестов производительности, но этот вид настройки обычно дает мне хорошее представление о производительности различий)
Тест: С 10 целых чисел в списке, а другой с 100.000
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
private static Stopwatch timer = new Stopwatch();
static void Main(string[] args)
{
/// Initialization
var _linkedList = new LinkedList<int>();
for (int i = 0; i < 10; i++)
_linkedList.AddLast(i);
/// Test 1
timer.Start();
for (var _node = _linkedList.First; _node != _linkedList.Last; _node = _node.Next)
FuncFoo(_node.Value);
timer.Stop();
Console.WriteLine("For Loop: " + timer.Elapsed);
timer.Reset();
/// Test 2
timer.Start();
foreach (var _int in _linkedList)
FuncFoo(_int);
timer.Stop();
Console.WriteLine("Foreach Loop: " + timer.Elapsed);
timer.Reset();
/// Test 3
timer.Start();
var _listNode = _linkedList.First;
while (_listNode != _linkedList.Last)
{
FuncFoo(_listNode.Value);
_listNode = _listNode.Next;
}
timer.Stop();
Console.WriteLine("While Loop: " + timer.Elapsed);
timer.Reset();
///End
Console.Write("Press any key to continue...");
Console.ReadKey();
}
private static void FuncFoo(int _num)
{
_num = (int)Math.Sqrt(1 + 2 + 3 + 4 + 5) * _num;
}
}
}
Результаты: 10 целых чисел в списке
For Loop: 0.0002371
Foreach Loop: 0.0002880
While Loop: 0.0000002
Результаты: 100000 целых чисел в списке
For Loop: 0.0013548
Foreach Loop: 0.0015256
While Loop: 0.0013436
Итак, 2 вещи, о которых я не знаю.
Почему цикл for намного медленнее, чем цикл while? Я думал, что цикл for работает как цикл while за кулисами? (Я понимаю, почему цикл foreach немного медленнее во всех случаях)
Почему цикл while становится менее эффективным по мере добавления большего количества элементов в связанный список? Я полагал, что они будут все более или менее оставаться в одном и том же соотношении (например, для foreach loops). Но видеть, что цикл while, казалось бы, теряет производительность (или for/foreach gain performance?) Меня смущает.
Я предполагаю, что мой код, вероятно, не функционировал в качестве теста (В этом случае я хотел бы знать, что я сделал неправильно/почему, так что я знаю, как сделать более надежные тесты в будущем). Но в случае, если это действительный тест, я хотел бы знать, что вызывает эти кажущиеся странными результаты (даже если разница в производительности не изменит мой код).
Выполнение 'foreach' теряется из-за дополнительных накладных расходов в' Enumerator.MoveNext() '. 'LinkedList .Enumerator.Dispose()' ничего не делает, и я считаю, что накладные расходы try/catch также несущественны. –
Kimi
Пробные блоки могут повлиять на производительность. В этом случае он может быть не фактическим ботом в общем случае. –
Спасибо, что нашли время, чтобы ответить на него, думаю, я знал меньше, чем я думал, что знаю. Могу ли я спросить, как работает оптимизация (путем запуска большого количества непроверенных версий перед началом работы). К сожалению, я не понимаю кода MSIL или того, как работает JIT, я попытался получить базовое понимание, но я никогда не испытывал ДЕЙСТВИТЕЛЬНО. Мне также интересно, как работает каждый тест в миллион раз, меняет результат (отдельный для предварительной оптимизации). Означает ли это, что невозможно определить скорость каждого отдельного цикла? Или это совсем неважно? – Lolop