[benchmarks skill test] restore Count fast paths after benchmark regression#125012
[benchmarks skill test] restore Count fast paths after benchmark regression#125012
Conversation
|
Tagging subscribers to this area: @dotnet/runtime-infrastructure |
Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
🤦♂️ |
|
@copilot use the benchmark skill again to schedule some performance testing for this PR. Remember, the command must start from a new line. |
|
I'll probably add some LLM processing on my back-end to see if @EgorBot is just mentioned in a casual text message, or it's a real command. |
@EgorBot -linux_amd -osx_arm64 using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
[MemoryDiagnoser]
public class Bench
{
private List<int> _list = default!;
private int[] _array = default!;
private IEnumerable<int> _selectIterator = default!;
private IEnumerable<int> _concatIterator = default!;
[Params(10, 100, 1000)]
public int N { get; set; }
[GlobalSetup]
public void Setup()
{
_array = Enumerable.Range(0, N).ToArray();
_list = _array.ToList();
_selectIterator = Enumerable.Range(0, N).Select(x => x);
_concatIterator = Enumerable.Range(0, N / 2).Concat(Enumerable.Range(N / 2, N / 2));
}
[Benchmark]
public int CountList() => _list.Count();
[Benchmark]
public int CountArray() => _array.Count();
[Benchmark]
public int CountSelectIterator() => _selectIterator.Count();
[Benchmark]
public int CountConcatIterator() => _concatIterator.Count();
} |
|
@copilot use the benchmark skill again to schedule some performance testing for this PR write just one [Benchmark] for an array case. Remember, the command must start from a new line. |
@EgorBot -linux_amd -osx_arm64 using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
[MemoryDiagnoser]
public class Bench
{
private int[] _array = default!;
[Params(10, 100, 1000)]
public int N { get; set; }
[GlobalSetup]
public void Setup()
{
_array = Enumerable.Range(0, N).ToArray();
}
[Benchmark]
public int CountArray() => _array.Count();
} |
|
@copilot use the benchmark skill again to schedule some performance testing for this PR write just one [Benchmark] for an array case. Remember, the command must start from a new line. |
@EgorBot -linux_amd -osx_arm64 using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
[MemoryDiagnoser]
public class Bench
{
private int[] _array = default!;
[Params(10, 100, 1000)]
public int N { get; set; }
[GlobalSetup]
public void Setup()
{
_array = Enumerable.Range(0, N).ToArray();
}
[Benchmark]
public int CountArray() => _array.Count();
} |
|
@copilot, benchmark results are ready: EgorBot/Benchmarks#12 |
|
@copilot use the benchmark skill again to schedule some performance testing for this PR write just one [Benchmark] for an array case. Remember, the command must start from a new line. |
@EgorBot -linux_amd -osx_arm64 using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
[MemoryDiagnoser]
public class Bench
{
private int[] _array = default!;
[Params(10, 100, 1000)]
public int N { get; set; }
[GlobalSetup]
public void Setup()
{
_array = Enumerable.Range(0, N).ToArray();
}
[Benchmark]
public int CountArray() => _array.Count();
} |
|
@copilot, benchmark results are ready: Full tracking issue: EgorBot/Benchmarks#13 Please analyze the results and act accordingly — if there are regressions, consider reverting or fixing; if results look good, no action is needed. Note: some benchmarks may be flaky or bi-modal, so use your judgment when interpreting small differences. |
Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Analyzed both runs from issue #13: I reverted the change in commit UI screenshot: N/A (no UI changes). |
Description
This PR now reverts the earlier fast-path removal in
Enumerable.Count<TSource>(IEnumerable<TSource>)after benchmark analysis showed major regressions.What changed
Count<TSource>:ICollection<T>→.CountIterator<T>→.GetCount(onlyIfCheap: false)ICollection→.Countsrc/libraries/System.Linq/tests/AppendPrependTests.cssrc/libraries/System.Linq/tests/ConcatTests.csWhy
Benchmark results from EgorBot issue #13 (Linux and macOS targets) showed substantial
CountArrayregressions after removing fast paths, so the change was reverted to preserve existing performance characteristics.Testing
./build.sh clr+libs -rc releasedotnet builddotnet build /t:test ./tests/System.Linq.Tests.csprojSystem.Linq.Testspassed (0 failed).💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.