为什么在众多查询工具中,大家普遍不推崇使用Linq进行数据操作?

摘要:相信很多.NETer看了标题,都会忍不住好奇,点进来看看,并且顺便准备要喷作者! 这里,首先要申明一下,作者本人也非常喜欢Linq,也在各个项目中常用Linq。 我爱Linq,Linq优雅万岁!!!(PS:顺便吐槽一下,隔壁Java从8.0
相信很多.NETer看了标题,都会忍不住好奇,点进来看看,并且顺便准备要喷作者! 这里,首先要申明一下,作者本人也非常喜欢Linq,也在各个项目中常用Linq。 我爱Linq,Linq优雅万岁!!!(PS:顺便吐槽一下,隔壁Java从8.0版本推出的Streams API,抄了个四不像,一点都不优雅,而且很难用。)​ 正文 不罗嗦,就一句话:“在性能敏感型应用和追求零内存分配场景不推荐使用Linq!” 让我们用Benchmark结果来说话!!! 这里用一个简单的场景来验证: 拆分一个String字符串为String[]数组。 转换数组中的每个String字符串为​Int32数值。 对这些数值求和​。 让我们通过BenchmarkDotNet运行性能测试,看看用Linq和不用Linq,这两者之间的性能差异​。 Benchmark代码: internal class Program { static void Main(string[] args) { BenchmarkRunner.Run<LinqTest>(); Console.ReadKey(); } } ​ [MemoryDiagnoser, MemoryRandomization] public class LinqTest { private static readonly string _row = "1,2,3,4,5,6,7,8,9,10"; ​ [Benchmark] public void SumUsingLinq() { int sum = _row.Split(',').Select(int.Parse).Sum(); } ​ [Benchmark(Baseline = true)] public void SumUsingForLoop() { var rowSpan = _row.AsSpan(); int sum = 0; for (int i = 0; i < rowSpan.Length; i++) { if (rowSpan[i] == ',') { sum += int.Parse(rowSpan.Slice(0, i)); rowSpan = rowSpan.Slice(i + 1); i = 0; } } } } 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: 想要坚持写技术文章、写博客、写公众号,真的很难。 2024-06-26 更新 很多人觉得这个对比不公平: 不应该用Spilt, 不应该调用Select,可以把Parse放到Sum方法里处理。 经过网友调整代码后,再次测试下来,也依然有少量的内存分配,32B,Mean平均值依然相差18ns左右。 以下是网友修改代码后的测试结果