I created a list of 1,000,000 integers (range:[0,99]), and random select one target value, and count from the list using two method:
lst.Count(v => v == target);
lst.Where(v => v == target).Count();
I suppose the second way is doing more work than the first one, but benchmark shows that using where before count is 2~3 times faster than Count(contidion), why?
Dotnet 5.0 is used, by the way.
I am using BenchmarkDotNet, and I changed the list length to 100,000,000, the resut is the same. I also tried this.numbers.Where(v => v == target).Count(v => v == target)
, it's still faster than the first one.
This is the code I used:
[MemoryDiagnoser]
public class TestLinq
{
private readonly List<int> numbers;
private readonly Random rand = new Random();
public TestLinq()
{
this.numbers = new List<int>();
this.Prepare();
}
private void Prepare()
{
for (var i = 0; i < 100000000; i++)
{
this.numbers.Add(rand.Next(0, 99));
}
}
[Benchmark]
public void CountDirectly()
{
var target = rand.Next(0, 99);
var result = this.numbers.Count(v => v == target);
}
[Benchmark]
public void WhereThenCount()
{
var target = rand.Next(0, 99);
var result = this.numbers.Where(v => v == target).Count();
}
}
the result is
Method | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
---|---|---|---|---|---|---|---|---|
CountDirectly | 735.0 ms | 13.47 ms | 28.42 ms | 720.6 ms | - | - | - | 464 B |
WhereThenCount | 212.9 ms | 2.59 ms | 2.16 ms | 213.3 ms | - | - | - | 480 B |
and if change to this.numbers.Where(v => v == target).Count(v => v == target)
, it's still faster than the fist one
Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
---|---|---|---|---|---|---|---|
CountDirectly | 723.2 ms | 14.07 ms | 14.45 ms | - | - | - | 464 B |
WhereThenCount | 419.2 ms | 4.34 ms | 4.06 ms | - | - | - | 560 B |