Изучаю LINQ, почему-то он работает несколько медленно.
Создаю словарь с рандомными данными:
public static class GenerateCollection
{
private static readonly Random random = new();
public static Dictionary<string, int> Get(int workersNum)
{
Dictionary<string, int> stuff = new();
while (stuff.Count < workersNum)
{
var workerName = Path.GetRandomFileName()[..4];
var workerGrade = random.Next(1, 100);
stuff[workerName] = workerGrade;
}
return stuff;
}
}
Беру два метода, один считает среднее при помощи LINQ, второй - "вручную", при помощи foreach:
public static class LinqMethods
{
public static double Average(Dictionary<string, int> stuff) => stuff.Average(stuff => stuff.Value);
}
и
public static class ManualMethods
{
public static double Average(Dictionary<string, int> stuff)
{
long sum = 0;
checked
{
foreach (var worker in stuff)
{
sum += worker.Value;
}
}
return (double) sum / stuff.Count;
}
}
Сравниваю при помощи BenchmarkDotNet:
public class LinqVsManual
{
private Dictionary<string, int> _stuffA = new();
[Params(1_000, 10_000, 100_000)]
public int WorkersNum { get; set; }
[IterationSetup]
public void Setup()
{
_stuffA = GenerateCollection.Get(WorkersNum);
}
[Benchmark]
public double ManualAverage()
{
return ManualMethods.Average(_stuffA);
}
[Benchmark]
public double LinqAverage()
{
return LinqMethods.Average(_stuffA);
}
}
internal class Program
{
private static void Main()
{
BenchmarkRunner.Run<LinqVsManual>();
}
}
Получаю:
| Method | WorkersNum | Mean |
|-------------- |----------- |-------------:|
| ManualAverage | 1000 | 2.879 us |
| LinqAverage | 1000 | 12.792 us |
| ManualAverage | 10000 | 28.673 us |
| LinqAverage | 10000 | 115.260 us |
| ManualAverage | 100000 | 391.715 us |
| LinqAverage | 100000 | 1,158.016 us |
Думаю, это не LINQ настолько медленный, это я где-то ошибся, т. к. фактически повторяю код из github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq. Но где?