技術(shù)頻道導(dǎo)航
HTML/CSS
.NET技術(shù)
IIS技術(shù)
PHP技術(shù)
Js/JQuery
Photoshop
Fireworks
服務(wù)器技術(shù)
操作系統(tǒng)
網(wǎng)站運(yùn)營

贊助商

分類目錄

贊助商

最新文章

搜索

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

作者:admin    時間:2022-7-4 17:8:28    瀏覽:

asp.net(c#)中foreach和for循環(huán)的性能差異表現(xiàn)在它們的速度快慢上,在這篇文章中,我們探討一下這兩者的細(xì)微差異。

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

讓我們看一下下面的代碼:

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

foreach 在編譯器中會被轉(zhuǎn)換為以下代碼:

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執(zhí)行的整個過程:

  • 創(chuàng)建一個新對象,它被稱為Creator。
  • 每次迭代都會調(diào)用 MoveNext 方法。
  • 每次迭代都會訪問 Current 屬性。

不過,它并不像聽起來那么容易。

C#/CLR 可能會在運(yùn)行時執(zhí)行優(yōu)化,使代碼運(yùn)行得更快。

數(shù)組是一種深度集成到 CLR 中的類型,CLR 為這種類型提供了許多優(yōu)化。FOREACH 循環(huán)是一個可迭代的實(shí)體,這是性能的一個關(guān)鍵方面。在本文后面,我們將討論如何在 Array.ForEach 靜態(tài)方法和 List.ForEach 方法的幫助下遍歷數(shù)組和列表。

測試方法

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;
}

測試條件:

  • “優(yōu)化代碼”選項(xiàng)已打開。
  • 元素的數(shù)量等于 100 000 000(在數(shù)組和列表中)。
  • PC 規(guī)格:Intel Core i-5 和 8 GB RAM。

數(shù)組

 

該圖顯示 FORFOREACH 在遍歷數(shù)組時花費(fèi)相同的時間。也是因?yàn)镃LR優(yōu)化將FOREACH轉(zhuǎn)換為FOR,并以數(shù)組的長度作為最大迭代邊界。不管數(shù)組長度是否緩存(使用FOR時),結(jié)果都差不多。

聽起來可能很奇怪,但是緩存數(shù)組長度可能會影響性能。在使用Array.Length 作為迭代邊界時,JIT 測試索引是否命中循環(huán)之外的右邊界。此檢查僅執(zhí)行一次。

破壞這種優(yōu)化非常容易。緩存變量的情況幾乎沒有優(yōu)化。

Array.foreach展示了最差的結(jié)果。它的實(shí)現(xiàn)非常簡單: 

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

那為什么它運(yùn)行這么慢?它在引擎蓋下使用 FOR。原因在于調(diào)用 ACTION 委托。事實(shí)上,每次迭代都會調(diào)用一個方法,這會降低性能。此外,委托的調(diào)用速度沒有我們希望的那么快。

列表

 

結(jié)果完全不同。迭代列表時,FORFOREACH 顯示不同的結(jié)果。沒有優(yōu)化。FOR(緩存列表長度)顯示最佳結(jié)果,而 FOREACH 慢 2 倍以上。這是因?yàn)樗诤笈_處理 MoveNextCurrent。List.ForEachArray.ForEach 顯示最差的結(jié)果。代表總是被虛擬調(diào)用。此方法的實(shí)現(xiàn)如下所示:

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);
}

每次迭代都會調(diào)用 Action 委托。它還檢查列表是否更改,如果更改,則拋出異常。

List 內(nèi)部使用基于數(shù)組的模型,而 ForEach 方法使用數(shù)組索引進(jìn)行迭代,這比使用索引器快得多。 

 

具體數(shù)字

  1. 沒有長度緩存的 FOR 循環(huán)和 FOREACH 在數(shù)組上的工作比使用長度緩存的 FOR 稍快。
  2. Foreach 性能 比 FOR / FOREACH 性能慢大約 6 倍。
  3. 與數(shù)組相比,沒有長度緩存的 FOR 循環(huán)在列表上的運(yùn)行速度要慢 3 倍。
  4. 與數(shù)組相比,具有長度緩存的 FOR 循環(huán)在列表上的運(yùn)行速度要慢 2 倍。
  5. 與數(shù)組相比,FOREACH 循環(huán)在列表上的運(yùn)行速度要慢 6 倍。

這是列表的排行榜: 

 

對于數(shù)組:

 

結(jié)論

事實(shí)證明,FOREACH 在數(shù)組上比 FOR 的長度追蹤更快。在列表結(jié)構(gòu)上,FOREACHFOR 慢。

使用 FOREACH 時代碼看起來更好,并且現(xiàn)代處理器允許使用它。但是,如果你需要高度優(yōu)化你的代碼庫,最好使用 FOR。

文章推薦

標(biāo)簽: foreach  for  
相關(guān)文章
    x
    • 站長推薦
    /* 左側(cè)顯示文章內(nèi)容目錄 */