• 为什么不推荐使用Linq?


    相信很多.NETer看了标题,都会忍不住好奇,点进来看看,并且顺便准备要喷作者!

    这里,首先要申明一下,作者本人也非常喜欢Linq,也在各个项目中常用Linq。

    我爱Linq,Linq优雅万岁!!!(PS:顺便吐槽一下,隔壁Java从8.0版本推出的Streams API,抄了个四不像,一点都不优雅,而且很难用。)​

    正文

    不罗嗦,就一句话:“在性能敏感型应用和追求零内存分配场景不推荐使用Linq!

    让我们用Benchmark结果来说话!!!

    这里用一个简单的场景来验证:

    1. 拆分一个String字符串为String[]数组。
    2. 转换数组中的每个String字符串为​Int32数值。
    3. 对这些数值求和​。

    让我们通过BenchmarkDotNet运行性能测试,看看用Linq和不用Linq,这两者之间的性能差异​。

    Benchmark代码:

    internal class Program
    {
        static void Main(string[] args)
        {
            BenchmarkRunner.Run();
            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 更新

    很多人觉得这个对比不公平:

    1. 不应该用Spilt,
    2. 不应该调用Select,可以把Parse放到Sum方法里处理。

    经过网友调整代码后,再次测试下来,也依然有少量的内存分配,32B,Mean平均值依然相差18ns左右。

    以下是网友修改代码后的测试结果

  • 相关阅读:
    面试无头绪?10w+字总结的Java面试题(附答案),够你刷的了!!
    C++标准模板(STL)- 类型支持 (数值极限,round_style,is_iec559,is_bounded)
    自动驾驶---Perception之视觉点云&雷达点云
    vue项目中 commonJS转es6
    主变10kv 220kV、容量63MVA的风电场设计
    有哪些可以投稿软件工程/系统软件/程序设计语言类外文期刊、会议?
    学会用命令行创建uni-app项目并用vscode开放项目
    系统整理K8S的配置管理实战-建议收藏系列
    【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
    cf #832 Div.2(A-D)
  • 原文地址:https://www.cnblogs.com/VAllen/p/18268012/why-not-recommend-using-linq