Что за ерунда наблюдается.
В примере создаются 2 Одинаковых делегата(Ели ели нашел что в них дело, проверяя 1000 комбинаций причин), тот кто первый запустится будет в 10 раз быстрее. Почему так происходит, неожиданно поймал такое.
Вот для простоты пример, замеряю работу функции, создал расширение For для выполнения N раз функции для элементов массивов, без него эффект не наблюдается, если допустим цикл внутрь m(()=>{for....}); вставить.
Немного подебажил, и вроде заметил, что второй в порядке вызова метод вообще не инлайнится, и там прям стандартный метод вместо хотя бы 2 инструкций "lea lea eax, [rcx + rdx]; ret" там 10-20 как в debug режиме.
var arr=Enumerable.Range(0,1_000_000).Select(i=> (X:(uint)i, Y: 1u)).ToArray(); // от n не зависит, (кортеж артефакт поиска причины )
// одинаковые делегаты, второй в порядке вызывания будет до 10-100 раз медленнее!!!!
var del = () => arr.For ((a) => test1(a.Item1, a.Item2));
var del2 = () => arr.For ((a) => test1(a.Item1, a.Item2));
m(del); // зависит от порядка вызова
m(del2);
// какая-то случ функция до 50 асемблерных строк всяких инструкций эффект наблюдается где-то
static uint test1(uint i, uint j)
{
return i + j;
}
public static class ArrayExtensions{
public static void For <T>(this T[] arr, Action<T> func)
{
int len = arr.Length;
foreach(var i in arr)
{
func(i);
}
}
}
public static void m(Action action, Action load = null)
{
Stopwatch sw = Stopwatch.StartNew();
load?.Invoke();
action();
load?.Invoke();
sw.Start();
action();
sw.Stop();
int n = (int)(5_000 / (sw.Elapsed.TotalMilliseconds + 0.001f));
if (n == 0)
n = 1;
List<double> times = new List<double>();
for (int i = 0; i < n; i++)
{
load?.Invoke();
sw.Restart();
action();
sw.Stop();
times.Add(sw.Elapsed.TotalMilliseconds);
}
double sum = times.Sum();
double average = sum / n;
double err = Math.Sqrt(times.Aggregate(0.0, (acc, e) => acc += (e - average) * (e - average)) / (n - 1));
Console.WriteLine($"Test func: {action.Method.Name}");
Console.WriteLine($"Count invoke: {n}");
Console.WriteLine("Standard deviation: {0,20:f4} ms", err);
Console.WriteLine("Max: {0,20:f4} ms", times.Max());
Console.WriteLine("Min: {0,20:f4} ms", times.Min());
var c1 = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Mean time : {0,20:f4} ms", average);
Console.ForegroundColor = c1;
Console.WriteLine();
}
Test func: b__1
Count invoke: 5803
Standard deviation: 0.0146 ms
Max: 0.3772 ms
Min: 0.0362 ms
Mean time : 0.0509 ms
Test func: b__1
Count invoke: 55555
Standard deviation: 0.0091 ms
Max: 0.4715 ms
Min: 0.0355 ms
Mean time : 0.0420 ms
Test func: b__2
Count invoke: 3902
Standard deviation: 0.0589 ms
Max: 0.9081 ms
Min: 0.3880 ms
Mean : 0.4358 ms
Test func: b__2
Count invoke: 6124
Standard deviation: 0.0519 ms
Max: 0.7931 ms
Min: 0.3880 ms
Mean : 0.4263 ms