技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

asp.net(c#) foreach和for速度比较

作者:admin    时间:2022-7-4 17:8:28    浏览:

asp.net(c#)中foreach和for循环的性能差异表现在它们的速度快慢上,在这篇文章中,我们探讨一下这两者的细微差异。

asp.net(c#) foreach和for速度比较 

让我们看一下下面的代码:

foreach (var item in Enumerable.Range(0, 128))
{
  Console.WriteLine(item);
}

foreach 在编译器中会被转换为以下代码:

IEnumerator<int> enumerator = Enumerable.Range(0, 128).GetEnumerator();
try
 {
   while (enumerator.MoveNext())
   {
     int item = enumerator.Current;
     Console.WriteLine(item);
   }
 }
finally
 {
  if (enumerator != null)
  {
   enumerator.Dispose();
  }
}

可以看到,foreach执行的整个过程:

  • 创建一个新对象,它被称为Creator
  • 每次迭代都会调用 MoveNext 方法。
  • 每次迭代都会访问 Current 属性。

不过,它并不像听起来那么容易。

C#/CLR 可能会在运行时执行优化,使代码运行得更快。

数组是一种深度集成到 CLR 中的类型,CLR 为这种类型提供了许多优化。FOREACH 循环是一个可迭代的实体,这是性能的一个关键方面。在本文后面,我们将讨论如何在 Array.ForEach 静态方法和 List.ForEach 方法的帮助下遍历数组和列表。

测试方法

static double ArrayForWithoutOptimization(int[] array)
{
   int sum = 0;
   var watch = Stopwatch.StartNew();
   for (int i = 0; i < array.Length; i++)
     sum += array[i];
    watch.Stop();
    return watch.Elapsed.TotalMilliseconds;
}

static double ArrayForWithOptimization(int[] array)
{
   int length = array.Length;
   int sum = 0;
   var watch = Stopwatch.StartNew();
    for (int i = 0; i < length; i++)
      sum += array[i];
    watch.Stop();
     return watch.Elapsed.TotalMilliseconds;
}

static double ArrayForeach(int[] array)
{
  int sum = 0;
  var watch = Stopwatch.StartNew();
   foreach (var item in array)
    sum += item;
  watch.Stop();
  return watch.Elapsed.TotalMilliseconds;
}

static double ArrayForEach(int[] array)
{
  int sum = 0;
  var watch = Stopwatch.StartNew();
  Array.ForEach(array, i => { sum += i; });
  watch.Stop();
  return watch.Elapsed.TotalMilliseconds;
}

测试条件:

  • “优化代码”选项已打开。
  • 元素的数量等于 100 000 000(在数组和列表中)。
  • PC 规格:Intel Core i-5 和 8 GB RAM。

数组

 

该图显示 FORFOREACH 在遍历数组时花费相同的时间。也是因为CLR优化将FOREACH转换为FOR,并以数组的长度作为最大迭代边界。不管数组长度是否缓存(使用FOR时),结果都差不多。

听起来可能很奇怪,但是缓存数组长度可能会影响性能。在使用Array.Length 作为迭代边界时,JIT 测试索引是否命中循环之外的右边界。此检查仅执行一次。

破坏这种优化非常容易。缓存变量的情况几乎没有优化。

Array.foreach展示了最差的结果。它的实现非常简单: 

public static void ForEach<T>(T[] array, Action<T> action)
 {
  for (int index = 0; index < array.Length; ++index)
    action(array[index]);
 }

那为什么它运行这么慢?它在引擎盖下使用 FOR。原因在于调用 ACTION 委托。事实上,每次迭代都会调用一个方法,这会降低性能。此外,委托的调用速度没有我们希望的那么快。

列表

 

结果完全不同。迭代列表时,FORFOREACH 显示不同的结果。没有优化。FOR(缓存列表长度)显示最佳结果,而 FOREACH 慢 2 倍以上。这是因为它在后台处理 MoveNextCurrentList.ForEachArray.ForEach 显示最差的结果。代表总是被虚拟调用。此方法的实现如下所示:

public void ForEach(Action<T> action)
{
  int num = this._version;
   for (int index = 0; index < this._size && num == this._version; ++index)
     action(this._items[index]);
   if (num == this._version)
     return;
   ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}

每次迭代都会调用 Action 委托。它还检查列表是否更改,如果更改,则抛出异常。

List 内部使用基于数组的模型,而 ForEach 方法使用数组索引进行迭代,这比使用索引器快得多。 

 

具体数字

  1. 没有长度缓存的 FOR 循环和 FOREACH 在数组上的工作比使用长度缓存的 FOR 稍快。
  2. Foreach 性能 比 FOR / FOREACH 性能慢大约 6 倍。
  3. 与数组相比,没有长度缓存的 FOR 循环在列表上的运行速度要慢 3 倍。
  4. 与数组相比,具有长度缓存的 FOR 循环在列表上的运行速度要慢 2 倍。
  5. 与数组相比,FOREACH 循环在列表上的运行速度要慢 6 倍。

这是列表的排行榜: 

 

对于数组:

 

结论

事实证明,FOREACH 在数组上比 FOR 的长度追踪更快。在列表结构上,FOREACHFOR 慢。

使用 FOREACH 时代码看起来更好,并且现代处理器允许使用它。但是,如果你需要高度优化你的代码库,最好使用 FOR

文章推荐

标签: foreach  for  
相关文章
    x
    x
    • 站长推荐