LINQ 和性能

介绍

自从微软在 .NET 3.5 中引入LINQ已经 15 年(2007 年) 。这应该有足够的时间让它成熟为一个全方位的有用工具。

LINQ的使用有几个方面:

  • 延迟执行和延迟评估(更好地利用多线程系统)
  • 缩短代码(可读性和可重用性)
  • 所用技术的运行时开销(性能)

在本文中,我将只了解 LINQ 的一个方面——性能。

背景

LINQ - 至少在我的环境中 - 以其外观使所有 C# 程序员兴奋不已,随后导致该技术的大量使用。

我想在这里问一下,如果一个人完全清醒地看待 LINQ:作为扩展方法匿名委托(lambda 表达式)与延迟执行(yield)的创新组合,还有多少营销亮点?

为了从性能方面回答这个问题,我想用 LINQ 过滤一个对象列表并对结果进行排序。

这种方法的特殊性是 LINQ 必须处理列表直到最后一个元素。因此,我有意消除Any()使用or可以实现的运行时优势,First()并专注于必须处理所有元素的情况。

测试

当然,结果取决于底层运行时系统、操作系统和硬件的多线程能力——因此,仅将在同一环境中运行的不同方法相互比较是有用的。为此,我准备了 4 个可以相互比较的测试用例。

  • 测试用例 1:使用 C++ 的 LINQ(无排序和有排序)
  • 测试用例 2 :使用 C++ 的经典(for(...)循环if(...)和)(无排序和有排序)sort(...)
  • 测试用例 3:使用 C# 的 LINQ(无排序和有排序)
  • 测试用例 4:带有 C# 的经典(for(...)循环if(...)sort(...))(没有和有排序)

并且测试用例将在两个不同的环境中执行......

在Win10中测试

第一个测试环境是配备 i7-5600U @ 2.6GHz、Windows 10 x64、.NET 4.7.2 和 16GB 内存的 Lenovo T550。

C++ 测试结果如下:

C#测试结果如下:

在 openSUSE 上测试

第二个测试环境是联想 T520,配备 i5-2540M @ 2.6GHz、openSUSE Leap 15.4 x64、.NET 6.0 和 12 GB 内存。

C++ 测试结果如下:

C#测试结果如下:

结果比较

为了更好地比较结果,我忽略了最差的测试运行(最长的运行时间)并取其余三个测试运行的中值。这是这张摘要图片:

线系统硬件试图订购中位数C++ 与 C#LINQ 与经典
1赢得 10T550C++LINQ23.1 毫秒77 %worse差 2.5 倍
2赢得 10T550C#LINQ13.0 毫秒好 77 %
3赢得 10T550C++经典的9.2 毫秒73 %worse约好 2.5 倍
4赢得 10T550C#经典的5.3 毫秒好 73 %
5赢得 10T550C++LINQ是的19.0 毫秒好 186 %不一致的
6赢得 10T550C#LINQ是的54.3 毫秒差 186 %
7赢得 10T550C++经典的是的7.6 毫秒1309 % 更好不一致的
8赢得 10T550C#经典的是的107.1 毫秒差 1309 %
9openSUSET520C++LINQ11.5 毫秒好 60 %~ 3 倍差
10openSUSET520C#LINQ18.4 毫秒差 60%
11openSUSET520C++经典的5.1 毫秒平等的〜3倍好
12openSUSET520C#经典的5.1 毫秒平等的
13openSUSET520C++LINQ是的10.5 毫秒好 395 %不一致的
14openSUSET520C#LINQ是的52.0 毫秒差 395 %
15openSUSET520C++经典的是的5.1 毫秒23169 % 更好不一致的
16openSUSET520C#经典的是的123.4 毫秒差 23169 %

预期和结果的讨论

C++ 与 C#

  • 我期望 C++ 比 C# 有明显的优势。
  • 期望达到了。但是,并没有预期的那么一致。

除了第 1/2 行和第 3/4 行的突破之外,C++ 比 C# 更快——但并不显着。但是,只有通过排序,差异才会变得非常明显。显然,STL 和 C++ 编译器优化器在这里做得很好。这在第 7/8 行和第 15/16 行变得非常清楚——以一种几乎令人难以置信的方式。但是我已经重复了几次测试运行 - 结果没有显着变化。C# 总是失败。

LINQ 与经典(for(...) 循环、 if(...) 和 sort(...)

  • 我希望 LINQ 与经典方法相比有明显的劣势。
  • 期望达到了。然而,并没有想象中那么清晰。

对于 C++ 和 C# , LINQ 总是比经典方法(for(...)循环if(...)和)更糟糕。sort(...)但差异小于预期。

我认为 LINQ 在 C++ 中表现如此出色的原因是它是一个模板实现,可以转换为高度优化的机器代码。

我认为 LINQ 在 C# 中表现如此出色的原因是特殊的数据结构。C++ 中的 LINQvector<Element>用于源数据和结果,而 C# 中的 LINQList<Element>用于源数据和System.Linq.Enumerable.WhereListIterator<Element>/或System.Linq.OrderedEnumerable<Element, int>结果。第二个datatype 提供了对排序标准的明确访问,也可以被视为不再具有可比性或作弊。但让我们温和一点。

Wind10 与 openSUSE

我不想进一步评论它,但测试似乎在 Linux 下在较弱的硬件上运行得更快。也许是因为 Microsoft Defender - 它总是在我的 Windows 机器上运行。

缩放

与 C++ 相比,C# 相当可接受的结果让我感到惊讶(我曾预计至少有 10 次方作为差异),也让我感到高兴(显然 15 年的发展确实对 C# 产生了积极影响)。

不过,我想确定 C# 真的那么强大。640000所以我简单地将数据量从到乘以 20 倍12800000

缩放后的 C++ 测试结果为:

缩放后的 C# 测试结果为:

这是这张摘要图片:

线系统硬件试图订购中位数C++ 与 C#LINQ 与经典
1openSUSET520C++LINQ258.9 毫秒30 %worse~ 差 2 倍
2openSUSET520C#LINQ199.8 毫秒好 30%
3openSUSET520C++经典的135.4 毫秒21 %worse~ 好 2 倍
4openSUSET520C#经典的111.9 毫秒好 21%
5openSUSET520C++LINQ是的250.9 毫秒好 261 %不一致的
6openSUSET520C#LINQ是的906.2 毫秒差 261%
7openSUSET520C++经典的是的135.1 毫秒3224 % 更好不一致的
8openSUSET520C#经典的是的4491.5 毫秒差 322
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值