为什么线程比Parallel.Foreach更快打开OracleConnection?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么线程比Parallel.Foreach更快打开OracleConnection?相关的知识,希望对你有一定的参考价值。
我有两段代码如下,一个使用Thread,一个使用Parallel.Foreach
线
foreach (var i in new int [] {0, 1, 2, 3, 4, ..., 24 })
new Thread(GET_DATA).Start(i);
平行
Parallel.Foreach(new int [] {0, 1, 2, 3, 4, ..., 24 }, GET_DATA);
使用方法GET_DATA
void GET_DATA(object state) {
var x = (int)state;
using (var conn = new OracleConnection(cs[x])) {
conn.Open();
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "select * from dual";
var dt = new DataTable();
dt.Load(cmd.ExecuteReader());
}
}
}
和cs是25 Oracle Database的连接字符串数组
我使用Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
和16GB RAM
,来自nuget的Oracle.ManagedDataAccess库中的OracleConnection。
第一次,没有创建连接池时
Thread approach
:所有线程在运行后3到5秒停止Parallel approach
:跑步后12至15秒平行停止
在下一次,两种方法的结果相似,因为创建了连接池。
我想在单核上并行运行应该比线程慢近4倍,任何人都能解释一下吗?
谢谢
在第一个示例中,您生成了24个线程,它们将通过等待I / O操作(建立与数据库的套接字连接)来完成。
在第二个示例中,您使用未知数量的线程(取决于核心数和并行化设置的程度)来处理24个项目的列表。每个线程将以串行方式处理项目的子集。
由于操作在您的进程中不受CPU限制,而是依赖于外部进程(数据库的I / O,数据库上的操作等),Parallel.Foreach
将浪费大量时间等待一个任务完成之前开始下一个。
例
X是操作的完成,时间是垂直的,线程是水平的。
使用24个线程时:
1 2 3 ... 24 Time
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
X X X X V
使用4个线程处理24个项目时:
1 2 3 4 Time
| | | | |
| | | | |
| | | | |
X X X X |
| | | | |
| | | | |
| | | | |
X X X X |
| | | | |
| | | | |
| | | | |
X X X X |
. . . . |
. . . . |
. . . . V
Parallel.Foreach(new int [] {0, 1, 2, 3, 4, ..., 24 }, GET_DATA);
还请将此添加到Parallel.Foreach
以使两个样本使用相同数量的线程。
new ParallelOptions { MaxDegreeOfParallelism = 24 }
至于正常的foreach
,这将在退出循环之前等待所有线程完成
foreach (var i in new int [] {0, 1, 2, 3, 4, ..., 24 })
new Thread(GET_DATA).Start(i);
如果等待所有线程完成,我相信你会得到相同的结果。
以上是关于为什么线程比Parallel.Foreach更快打开OracleConnection?的主要内容,如果未能解决你的问题,请参考以下文章
Parallel.ForEach 没有提供更多内核的加速[关闭]
强制终止由 Parallel.ForEach 生成的线程 [重复]