为什么使用' foreach '在数组对象上循环比lambda ' foreach '快?
本文关键字:foreach 循环 lambda 为什么 数组 对象 | 更新日期: 2023-09-27 18:15:33
我处理一个数组,我必须在它上面循环。首先,我使用lambda ForEach
Array
.ForEach<int>( array, ( int counter ) => {
Console.WriteLine( counter );
} );
,然后我使用简单的foreach
。我发现简单的foreach
比lambda ForEach
快,但是当我用泛型列表测试它时,ForEach
比简单的foreach
快。
为什么循环数组对象与foreach
比lambda ForEach
快?更新:I测试数组
我稍微编辑了一下Keith的代码——在我的机器上,foreach
的执行速度大约是Array.ForEach
的6倍:
class Program
{
static void Main(string[] args)
{
Benchmark(50);
}
private static void Benchmark(int iterations)
{
int[] list = Enumerable.Range(0, 100000000).ToArray();
long sum = 0;
for (int i = 0; i < iterations; i++)
{
sum += ArrayForeach(list);
}
Console.WriteLine("ForEach " + sum / iterations);
sum = 0;
for (int i = 0; i < iterations; i++)
{
sum += Foreach(list);
}
Console.WriteLine("foreach " + sum / iterations);
}
private static long Foreach(int[] list)
{
long total = 0;
var stopWatch = Stopwatch.StartNew();
foreach (var i in list)
{
total += i;
}
stopWatch.Stop();
return stopWatch.ElapsedTicks;
}
private static long ArrayForeach(int[] list)
{
long total = 0;
var stopWatch = Stopwatch.StartNew();
Array.ForEach(list, x => total += x);
stopWatch.Stop();
return stopWatch.ElapsedTicks;
}
}
在我的机器上(可能运行的CLR与其他机器不同),它产生(在Release中):
ForEach 695910
foreach 123852
在调试中:
ForEach 941030
foreach 845443
- 这表明
- 在调试中,看起来运行lambda的开销和传递数字(按值)是造成差异的原因。
foreach
享受一些编译器优化,我猜主要是在访问内存中的列表。我建议有更多时间的人看看Reflector…
我发现lambda在我的测试中更快。复制粘贴msdn的秒表代码,并用迭代List的两个版本来装饰它....(我也改变了测试的顺序,我得到了相同的时间)。使用lambda的基于Linq的迭代速度更快。
Lambda 00:00:00.49
foreach 00:00:00.58
和代码…
var list = Enumerable.Range(0, 100000000).ToArray();
var total = 0;
var stopWatch = new Stopwatch();
stopWatch.Start();
Array.ForEach(list, x => total += x);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
stopWatch = new Stopwatch();
stopWatch.Start();
foreach (var i in list)
{
total += i;
}
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);