相信很多.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左右。
以下是网友修改代码后的测试结果
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容