gpt4 book ai didi

c# - 计算数组中的元素-性能-

转载 作者:行者123 更新时间:2023-12-02 19:17:32 24 4
gpt4 key购买 nike

我有这个数组: var arr = new int[] { 1, 1, 0, -1, -1 }; 我需要计算正数、负数和零数的数量。我使用 foreach 循环和 Linq 完成了此操作,并尝试使用 Stopwatch 来比较两种方法之间的性能,这是我的代码:

        int pos = 0, neg = 0, zeros = 0;
int p = 0, n = 0, z = 0;


Stopwatch sw = new Stopwatch();

sw.Start();

pos = arr.Sum(e => e > 0 ? 1 : 0);
neg = arr.Sum(e => e < 0 ? 1 : 0);
zeros = arr.Sum(e => e == 0 ? 1 : 0);

sw.Stop();


Stopwatch sw2 = new Stopwatch();

sw2.Start();

foreach (var item in arr)
{
if (item > 0) p++;
else if (item < 0) n++;
else z++;
}

sw2.Stop();

Console.WriteLine("Elapsed={0}", sw.Elapsed); //Elapsed=00:00:00.0008311
Console.WriteLine("Elapsed2={0}", sw2.Elapsed); //Elapsed2=00:00:00.0000028

结果表明,foreach 循环(28ms)比 Linq 方法(8311ms)好得多,所以我的问题是为什么会有这些差异表现如何?

我什至尝试了三个 foreach 循环,一个用于计算负数,一个用于计算正数,第三个用于计算零,但性能仍然比 Linq 方法好!

预先感谢您的帮助!

最佳答案

让我们以稍微不同的方式进行赛马:

private static string UnderTest(int size) {
int pos = 0, neg = 0, zeros = 0;
int p = 0, n = 0, z = 0;

Random random = new Random(0);
int[] arr = Enumerable
.Range(0, size)
.Select(x => random.Next(-1, 2))
.ToArray();
GC.Collect(GC.MaxGeneration);

Stopwatch sw = new Stopwatch();
sw.Start();

// Three Linq loops (expected to be 3 three times slower)
pos = arr.Sum(e => e > 0 ? 1 : 0);
neg = arr.Sum(e => e < 0 ? 1 : 0);
zeros = arr.Sum(e => e == 0 ? 1 : 0);

sw.Stop();

Stopwatch sw2 = new Stopwatch();
sw2.Start();

// Just 1 loop
foreach (var item in arr) {
if (item > 0) p++;
else if (item < 0) n++;
else z++;
}

sw2.Stop();

return $"{sw.Elapsed} vs. {sw2.Elapsed} ratio: {((double)sw.Elapsed.Ticks) / sw2.Elapsed.Ticks:f3}";
}

不同数组大小的竞争:

   int[] loops = new int[] {
1000,
10_000,
100_000,
1_000_000,
10_000_000,
100_000_000,
1000, // <- 1000 again
};

string report = string.Join(Environment.NewLine, loops
.Select(loop => $"loops: {loop,10} : {UnderTest(loop)}"));

Console.Write(report);

结果:

loops:       1000 : 00:00:00.0006471 vs. 00:00:00.0000114 ratio: 56.763 // <- Warming up
loops: 10000 : 00:00:00.0003195 vs. 00:00:00.0001074 ratio: 2.975
loops: 100000 : 00:00:00.0037131 vs. 00:00:00.0010910 ratio: 3.403
loops: 1000000 : 00:00:00.0351574 vs. 00:00:00.0118858 ratio: 2.958
loops: 10000000 : 00:00:00.3729617 vs. 00:00:00.1198276 ratio: 3.112
loops: 100000000 : 00:00:03.7002508 vs. 00:00:01.1808595 ratio: 3.134
loops: 1000 : 00:00:00.0000322 vs. 00:00:00.0000099 ratio: 3.253 // <- Expected

发生了什么:我们有 3 Linq 基于循环(3 调用 Sum),所以 Linq慢 3 倍(毫不奇怪)。然而,当系统加载程序集编译 IL代码等时,我们在第一次运行时遇到了巨大的异常值。所以你有一个所谓的热身效果。

关于c# - 计算数组中的元素-性能-,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60001866/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com