PLINQ 比此代码段的实际 Linq 慢

PLINQ slower than actual Linq for this snippet

下面是代码片段。使用EF6。

var itemNames = context.cam.AsParallel()
                    .Where(x=> x.cams == 
                     "edsfdf")
                    .Select(item => item.fg)
                    .FirstOrDefault();

为什么 PLINQ 比较慢?

如果您查看 .AsParallel() 的签名,它需要 IEnumerable<T>,而不是 IQueryable<T>。 linq 查询仅转换为 SQL 语句,同时保留为 IQueryable。一旦你枚举它,它就会执行查询并 returns 记录。

所以要分解您的查询:

context.cam.AsParallel()

这段代码本质上将在数据库上执行 SELECT * FROM cam,然后开始遍历 results.The,结果将传递到 ParallelQuery。这基本上会将整个 table 加载到内存中。

.Where(x=> x.cams == "edsfdf")
.Select(item => item.fg)
.FirstOrDefault()

在这一点之后,所有这些操作都将并行发生。与启动大量线程并管理它们之间的锁定和并发(PLINQ 会为您处理)的开销相比,简单的字符串相等性比较可能非常便宜。并行处理和 costs/benefits 是一个复杂的话题,但通常是 best saved for CPU-intensive work.

如果您跳过了 AsParallel() 调用,所有内容在整个 linq 语句中都保持为 IQueryable,因此 EntityFramework 将发送一个看起来像 SQL 的命令 SELECT fg FROM cam WHERE cams = 'edsfdf' 和 return 单个结果,SQL 服务器将优化为非常快速的查找,尤其是在摄像头上有索引的情况下。

慢是因为你用parralisim的地方不好。您的 Where 子句不执行繁重的工作,因此不适合使用 PLINQ。

If PLINQ comes with associated complexity then what is the real benefit for it's existence?

您不需要一百个人来寻找家中失踪的 child,因为找到 100 个人比自己寻找 child 花费的时间更长。但是如果你要搜索一个森林,这个开销是值得的,因为一个人在一个大森林里找到一个child比在一个大森林里找100个人寻找一个child需要更长的时间!

并行在正确的时间正确的地方使用是有效的。