from:https://blog.csdn.net/li315171406/article/details/78450534
最近要做一個大數據dataTable循環操作,開始發現 運用foreach,進行大數據循環,並做了一些邏輯處理。在循環中耗費的時間過長。后來換成使用Parallel.ForEach來進行循環。 一開始認為, 數據比較大時,Parallel.ForEach肯定比 ForEach效率高,后來發現,其實並不是這樣。
我用了1000萬次循環測試:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stopwatch Watch1 = new Stopwatch();
Watch1.Start();
List<entityA> source = new List<entityA>();
for (int i = 0; i < 10000000; i++)
{
source.Add(new entityA
{
name = "悟空" + i,
sex = i % 2 == 0 ? "男" : "女",
age = i
});
}
Watch1.Stop();
Console.WriteLine("list循環插入耗時:" + Watch1.ElapsedMilliseconds);
Stopwatch Watch2 = new Stopwatch();
Watch2.Start();
loop1(source);
Watch2.Stop();
Console.WriteLine("一般for循環耗時:" + Watch2.ElapsedMilliseconds);
Stopwatch Watch3 = new Stopwatch();
Watch3.Start();
loop2(source);
Watch3.Stop();
Console.WriteLine("一般foreach循環耗時:" + Watch3.ElapsedMilliseconds);
Stopwatch Watch4 = new Stopwatch();
Watch4.Start();
loop3(source);
Watch4.Stop();
Console.WriteLine("並行for循環耗時:" + Watch4.ElapsedMilliseconds);
Stopwatch Watch5 = new Stopwatch();
Watch5.Start();
loop4(source);
Watch5.Stop();
Console.WriteLine("並行foreach循環耗時:" + Watch5.ElapsedMilliseconds);
Console.ReadLine();
}
//普通的for循環
static void loop1(List<entityA> source)
{
int count = source.Count();
for (int i = 0; i < count; i++)
{
source[0].age= + 10;
//System.Threading.Thread.Sleep(10);
}
}
//普通的foreach循環
static void loop2(List<entityA> source)
{
foreach (entityA item in source)
{
item.age =+ 10;
//System.Threading.Thread.Sleep(10);
}
}
//並行的for循環
static void loop3(List<entityA> source)
{
int count = source.Count();
Parallel.For(0, count, item =>
{
//source[count].age= source[count].age + 10;
//System.Threading.Thread.Sleep(10);
});
}
//並行的foreach循環
static void loop4(List<entityA> source)
{
Parallel.ForEach(source, item =>
{
item.age = item.age + 10;
//System.Threading.Thread.Sleep(10);
});
}
}
//簡單的實體
class entityA
{
public string name { set; get; }
public string sex { set; get; }
public int age { set; get; }
}
}
運行結果:
結果居然是並行比一般的循環還耗時,但這是為什么呢?
這是因為循環體內執行的任務開銷太小,僅僅是age+10 而已。微軟的文章已經指出任務的開銷大小對並行任務的影響。如果任務很小,那么由於並行管理的附加開銷(任務分配,調度,同步等成本),可能並行執行並不是優化方案。這也是上述程序Foreach與For效率高出的原因。
基於這一點,我們對程序進行調整,循環1000次,每次里面線程sleep(10),這樣我們試試。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stopwatch Watch1 = new Stopwatch();
Watch1.Start();
List<entityA> source = new List<entityA>();
for (int i = 0; i < 1000; i++)
{
source.Add(new entityA
{
name = "悟空" + i,
sex = i % 2 == 0 ? "男" : "女",
age = i
});
}
Watch1.Stop();
Console.WriteLine("list循環插入耗時:" + Watch1.ElapsedMilliseconds);
Stopwatch Watch2 = new Stopwatch();
Watch2.Start();
loop1(source);
Watch2.Stop();
Console.WriteLine("一般for循環耗時:" + Watch2.ElapsedMilliseconds);
Stopwatch Watch3 = new Stopwatch();
Watch3.Start();
loop2(source);
Watch3.Stop();
Console.WriteLine("一般foreach循環耗時:" + Watch3.ElapsedMilliseconds);
Stopwatch Watch4 = new Stopwatch();
Watch4.Start();
loop3(source);
Watch4.Stop();
Console.WriteLine("並行for循環耗時:" + Watch4.ElapsedMilliseconds);
Stopwatch Watch5 = new Stopwatch();
Watch5.Start();
loop4(source);
Watch5.Stop();
Console.WriteLine("並行foreach循環耗時:" + Watch5.ElapsedMilliseconds);
Console.ReadLine();
}
//普通的for循環
static void loop1(List<entityA> source)
{
int count = source.Count();
for (int i = 0; i < count; i++)
{
source[0].age= + 10;
System.Threading.Thread.Sleep(10);
}
}
//普通的foreach循環
static void loop2(List<entityA> source)
{
foreach (entityA item in source)
{
item.age =+ 10;
System.Threading.Thread.Sleep(10);
}
}
//並行的for循環
static void loop3(List<entityA> source)
{
int count = source.Count();
Parallel.For(0, count, item =>
{
//source[count].age= source[count].age + 10;
System.Threading.Thread.Sleep(10);
});
}
//並行的foreach循環
static void loop4(List<entityA> source)
{
Parallel.ForEach(source, item =>
{
item.age = item.age + 10;
System.Threading.Thread.Sleep(10);
});
}
}
//簡單的實體
class entityA
{
public string name { set; get; }
public string sex { set; get; }
public int age { set; get; }
}
}
執行結果:
效率一目了然。
這樣的結果認證了我們上面的結論。當我們在循環中執行時間過長時,我們需要采用並行循環,效率較高。當時間過短,我們需要用foreach和for.
---------------------
作者:李江濤-Sir
來源:CSDN
原文:https://blog.csdn.net/li315171406/article/details/78450534
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
