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 效率问题研究及理解的更多相关文章

  1. C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?

    还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...

  2. php代码优化系列 -- array_walk 和 foreach, for 的效率的比较

    实验是我学习计算机科学的一个重要方法,计算机科学不是简单的智力游戏,它本质上来说不是一门科学,而是一个改造世界的工具.数学方法和实验方法是计算机研究的基本方法,也是我们学习的基本方法,数学锻炼我们的思 ...

  3. php代码优化 -- array_walk 和 foreach, for 的效率的比较

    <?php /** * array_walk 和 foreach, for 的效率的比较. * 我们要测试的是foreach, for, 和 array_walk的效率的问题. */ //产生一 ...

  4. C# for 和 foreach的执行效率

    for和foreach哪个执行效率快,相信很多人都会说当然是foreach快啊,在我实验之前我也是这么认为的,直到今天.费话不多说,下面是测试的结果,区分Debug和Release,数据采用int[] ...

  5. java8 for ,forEach ,lambda forEach , strean forEach , parller stream forEach, Iterator性能对比

    java8 for ,forEach ,Iterator,lambda forEach ,lambda  strean forEach , lambda parller stream forEach性 ...

  6. Parallel Programming-Paralle.For && ForEach

    本文主要介绍Parallel.For以及Parallel.ForEach.Parallel.For是普通步长为1的for循环的并行代替方案.Parallel.ForEach是以集合为基准进行循环的fo ...

  7. mybatis中foreach参数过多效率很慢的优化

    foreach 后面in 传入的参数有1万条,#和$是有效率区别的,$的效率远高于#,上篇文章做了比较. 但没达到我的理想结果. 1. 更改方式,把foreach 去掉,改成拼装方式, 参数直接拼装成 ...

  8. Foreach嵌套Foreach速度慢优化方案

    有时候这样的效率还可以,但是只要牵涉到操作数据库,那就GAMEOVER.. 最近在维护项目,一个Foreach循环,4分半才能出来结果. 代码: foreach ($content as $key = ...

  9. 多线程Parallel和Task

    不管是Parallel还是Task,最里面都是线程池(里面是线程)当开启多个任务后,系统会根据当前的线程池的资源进行分配,任务则进行等待Parallel可以对系统的CPU进行设置,可以最大程度上榨干系 ...

随机推荐

  1. sqoop 常用命令整理(一)

    这些内容是从sqoop的官网整理出来的,是1.4.3版本的Document,如果有错误,希望大家指正. 1.使用sqoop导入数据 sqoop import --connect jdbc:mysql: ...

  2. 【C】——C利用回调函数实现多态

    案例: 功能:可以根据用户输入的命令完成相应的功能: 例如: 用户输入  hello   完成输出 hello的功能.    用户输入  hi   完成输出 hi 的功能. 一般的写法可能会写两个函数 ...

  3. mongo 杀掉慢的程序killMyRunningOps("12.23.32.21") #####这个是客户端的ip

    mongodb运维(3) db.currentOp与db.killOp命令 2018.08.12 23:55 113浏览  字号 好久没更新mongo运维这块知识了,这次介绍 db.currentOp ...

  4. JDBC setCatalog

    数据库URL:jdbc:mysql://localhost:3306/{catalog} catalog指代数据库名称. 1如果该参数不存在,则必须使用setCatalog设置数据库名称,否则会抛出 ...

  5. Spring Cloud Config 配置中心高可用

    详细参见 <Spring Cloud 与 Docker微服务架构实战> p163-9.10 Spring Cloud Config 与 Eureka 配合使用 p163-9.12 Conf ...

  6. MongoDB 运行状态、性能监控,分析

    这篇文章的目的是让你知道怎么了解你正在运行的Mongdb是否健康.转载自http://tech.lezi.com/archives/290 mongostat详解 启动mongodb监控,通过下面命令 ...

  7. ubuntu 挂载硬盘

    https://cndaqiang.github.io/2017/10/11/ubuntu-disk/ 查看硬盘 查看方法一 查看/dev下面的设备文件 ll -h /dev/sd* 通过sudo f ...

  8. WM_CONCAT字符超过4000的处理办法

    参考网址: http://stackoverflow.com/questions/11541383/ordering-by-list-of-strings-in-oracle-sql-without- ...

  9. Linux操作系统的安装

    一.介绍 目的:通过本文了解并掌握Linux系统安装的过程 软件环境 Linux系统:CentOS7.3 虚拟机:VM12 主机系统:Windows8.0 二.安装虚拟机 首先,需要下载VMware ...

  10. Aizu_Insertion Sort

    原题链接:https://vjudge.net/problem/Aizu-ALDS1_1_A 题目描述 Write a program of the Insertion Sort algorithm ...