在C#中如何提高Linq的性能 c# linq性能
前言
C#的Linq语法直接,上手也简单,也易于理解.也能减少代码,现在在写代码的时候,使用Linq还是很多,遥想前些年很少使用的原因,是因为当时是使用的.NetFramework 3.5,使用Linq也有一点小缺点:
- Linq在.Net 8之前的版本性能稍微有点不太好.在.Net Framework中如果个别地方对性能要求高的,还是减少Linq的使用,使用for循环,合并计算,减少循环的次数
- 在.Net 8中,是对Linq的进行代码优化,使用SIMD(单指令多数据),性能提升还是很明显的
- 如果还没有使用.Net 8,还想使用Linq的语法,又需要性能,就需要第三方库比说SimdLinq(重点对象)/LinqFaster/NetFabric.Hyperlinq
当然SIMD也不是万能的银弹,目前只能对值类型(如int/long等类型)且计算密集的时候性能有所提升,主要减少CPU指令,让数据并行处理,而且SIMD要求数据对齐,从而提高内存使用效率.
本想写一个性能基准的测试,发现SimdLiq有一个性能测试的项目,便在笔记本跑了一次性能测试.调整SimdLinq的测试项目,改为.Net 7/.Net 8多版本测试.更新了BenchmarkDotNet的最新版本,不然BenchmarkDotNet无法识别.Net 8.
测试代码
public class IntSumBenchmark
{
readonly int[] source;
public IntSumBenchmark()
{
source = Enumerable.Range(1, 10000).ToArray();
var check = new[] { For(), LINQ(), SimdLinq(), LinqFasterSIMD(), Hyperlinq() }.Distinct().Count() == 1;
if (!check)
{
throw new Exception("invalid result exists");
}
}
[Benchmark]
public int For()
{
var array = source;
var sum = 0;
for (int i = 0; i < array.Length; i++)
{
sum += array[i];
}
return sum;
}
[Benchmark]
public int LINQ()
{
return Enumerable.Sum(source);
}
[Benchmark]
public int SimdLinq()
{
return SimdLinqExtensions.Sum(source); //SimdLinq的使用方式
}
[Benchmark]
public int LinqFasterSIMD()
{
return source.SumS();
}
[Benchmark]
public int Hyperlinq()
{
return source.AsValueEnumerable().Sum();
}
}
下面看一些测试的结果:
- for循环在.Net 7和.Net 8中,性能相差不大,在.Net 8中提升了4%的性能.
- Linq的Sum在.Net 7和.Net 8相差很大,在.Net 8中相比.Net 7中性能提升3倍还多.主要原因还是在Linq的代码使用SIMD进行性能优化.
- SimdLinq在.Net 7和.Net 8性能相差不大,很稳定,相比另外两个SIMD库,性能依然是最好的.
- LinqFaster在.Net 8中性能竟然有所下降,在.Net 7中和SimdLinq性能差距不是很大.
- NetFabric.Hyperlinq在.Net 8性能有所下降,不过比LinqFaster要一些.NetFabric.Hyperlinq和LinqFaster的性能还是比Linq的性能好.
个人能力有限,如果您发现有什么不对,请私信我
如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流