为什么不保举利用Linq?

打印 上一主题 下一主题

主题 908|帖子 908|积分 2724

相信许多.NETer看了标题,都会不由得好奇,点进来看看,而且顺便预备要喷作者!
这里,首先要说明一下,作者本人也非常喜欢Linq,也在各个项目中常用Linq。
我爱Linq,Linq优雅万岁!!!(PS:顺便吐槽一下,隔壁Java从8.0版本推出的Streams API,抄了个四不像,一点都不优雅,而且很难用。)​
正文
不罗嗦,就一句话:“在性能敏感型应用和追求零内存分配场景不保举利用Linq!”
让我们用Benchmark结果来语言!!!
这里用一个简单的场景来验证:

  • 拆分一个String字符串为String[]数组。
  • 转换数组中的每个String字符串为​Int32数值。
  • 对这些数值求和​。
让我们通过BenchmarkDotNet运行性能测试,看看用Linq和不消Linq,这两者之间的性能差异​。
Benchmark代码:
  1. internal class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         BenchmarkRunner.Run<LinqTest>();
  6.         Console.ReadKey();
  7.     }
  8. }
  9. [MemoryDiagnoser, MemoryRandomization]
  10. public class LinqTest
  11. {
  12.     private static readonly string _row = "1,2,3,4,5,6,7,8,9,10";
  13.     [Benchmark]
  14.     public void SumUsingLinq()
  15.     {
  16.         int sum = _row.Split(',').Select(int.Parse).Sum();
  17.     }
  18.     [Benchmark(Baseline = true)]
  19.     public void SumUsingForLoop()
  20.     {
  21.         var rowSpan = _row.AsSpan();
  22.         int sum = 0;
  23.         for (int i = 0; i < rowSpan.Length; i++)
  24.         {
  25.             if (rowSpan[i] == ',')
  26.             {
  27.                 sum += int.Parse(rowSpan.Slice(0, i));
  28.                 rowSpan = rowSpan.Slice(i + 1);
  29.                 i = 0;
  30.             }
  31.         }
  32.     }
  33. }
复制代码
Benchmark结果:

从结果中,我们可以看到,不利用Linq的SumUsingForLoop方法,Mean平均值 75.09 ns,Allocated 无;
反观利用了Linq的SumUsingLinq方法,Mean平均值 270.18 ns,Allocated 400 B;
两者之间有约3.5倍的性能差距,而内存分配表现方面也是不利用Linq的占优。
总结:
对于追求 零内存分配(zero-copy)目标 或者 速度敏感型应用,这两种场景,都应该​慎用Linq。因为Linq扩展方法里有大量的判断,甚至另有许多内部对象的创建和内存开销。
PS: 想要对峙写技术文章、写博客、写公众号,真的很难。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表