C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解
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
版权声明:本文为博主原创文章,转载请附上博文链接!
C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解的更多相关文章
- C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?
还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...
- php代码优化系列 -- array_walk 和 foreach, for 的效率的比较
实验是我学习计算机科学的一个重要方法,计算机科学不是简单的智力游戏,它本质上来说不是一门科学,而是一个改造世界的工具.数学方法和实验方法是计算机研究的基本方法,也是我们学习的基本方法,数学锻炼我们的思 ...
- php代码优化 -- array_walk 和 foreach, for 的效率的比较
<?php /** * array_walk 和 foreach, for 的效率的比较. * 我们要测试的是foreach, for, 和 array_walk的效率的问题. */ //产生一 ...
- C# for 和 foreach的执行效率
for和foreach哪个执行效率快,相信很多人都会说当然是foreach快啊,在我实验之前我也是这么认为的,直到今天.费话不多说,下面是测试的结果,区分Debug和Release,数据采用int[] ...
- java8 for ,forEach ,lambda forEach , strean forEach , parller stream forEach, Iterator性能对比
java8 for ,forEach ,Iterator,lambda forEach ,lambda strean forEach , lambda parller stream forEach性 ...
- Parallel Programming-Paralle.For && ForEach
本文主要介绍Parallel.For以及Parallel.ForEach.Parallel.For是普通步长为1的for循环的并行代替方案.Parallel.ForEach是以集合为基准进行循环的fo ...
- mybatis中foreach参数过多效率很慢的优化
foreach 后面in 传入的参数有1万条,#和$是有效率区别的,$的效率远高于#,上篇文章做了比较. 但没达到我的理想结果. 1. 更改方式,把foreach 去掉,改成拼装方式, 参数直接拼装成 ...
- Foreach嵌套Foreach速度慢优化方案
有时候这样的效率还可以,但是只要牵涉到操作数据库,那就GAMEOVER.. 最近在维护项目,一个Foreach循环,4分半才能出来结果. 代码: foreach ($content as $key = ...
- 多线程Parallel和Task
不管是Parallel还是Task,最里面都是线程池(里面是线程)当开启多个任务后,系统会根据当前的线程池的资源进行分配,任务则进行等待Parallel可以对系统的CPU进行设置,可以最大程度上榨干系 ...
随机推荐
- Extjs4.x Ext.tree.Panel 遍历当前节点下的所有子节点
Ext.define('WMS.controller.Org', { extend: 'Ext.app.Controller', stores: ['OrgUser', 'OrgTree'], mod ...
- 一款基于jquery和css3的头像恶搞特效
今天给大家分享一款基于jquery和css3的头像恶搞特效.这款实例中,一个头像在画面中跳舞,头像还有可爱的帽子,单击下面的按钮可以为头像切换不同的帽子.效果图如下: 在线预览 源码下载 实现的代 ...
- mxnet与tensorflow的卷积实现细节比较
mxnet的卷积 kernel = 3 pad=1边界补充0后,不管stride是否1还是2,imgw = 奇数或者偶数, 都是从图像位置(0,0)开始卷积 tensorlfow的卷积 kernel ...
- Axiom3D:Ogre动画基本流程与骨骼动画
在Axiom中,Animation类用于管理动画,在此对象中主要管理着AnimationTrack对象,此对象用于管理动画的各种类型的每一桢.在Axiom中,动画类型主要有变形动画,姿态动画,骨骼动画 ...
- SAP DBDI 网银接口实现案例
在财务共享中心SSC实施中,为了提高AP和对账的效率,不可避免的需要实现和网上银行的集成.笔者为各位分析该案例如下: 为什么要上网银? 2).和SAP的无缝集成 3).直接在SAP中和银联对接 4). ...
- 【转】【Centos】Centos下用upstart管理自己的服务程序
Upstart是Ubuntu用来进行服务进程管理的服务,本文介绍如何利用upstart来通过Centos操作系统管理我们自己开发的应用程序. 什么时候要管理我们的应用程序?当我们开发出服务类的应用程序 ...
- Android O 可以上网 提示无法访问网络
android O连接Wifi,可以上网,但是却提示无法访问网络,并且在wifi图标上有一个'x'. 从android N开始引入了监控机制,每次连接都会访问一下google的服务器,由于国内被墙,所 ...
- 事件的监听是由awt完成的
学swing 之前先学awt ,因为awt 是Java实现图形界面的基础. 它能够完成编写界面的基本功能,最重要的是,事件的监听是由awt完成的. 而swing是在awt基础上提供的新的界面工具包,它 ...
- Maven使用国内镜像
^_^ <mirrors> <!-- mirror | Specifies a repository mirror site to use instead of a given re ...
- Keystone-all 命令
本文档介绍Icehouse版keystone-all命令 keystone-all命令在一个进程中同时启动服务和管理API,为openstack提供服务目录,授权和身份认证服务. 用法 $ keyst ...