Optimize Enumerable.Range(...).Select(...) by stephentoub · Pull Request #37410 · dotnet/corefx (original) (raw)

Looking at some large code indexes, by far the most common uses of Enumerable.Range are when it's either directly iterated with a foreach, converted to an array with ToArray, or probably the most common, succeeded by Select (and then iterated or ToArray'd). The first two are already decently optimized, with a custom range iterator returned from Enumerable.Range and that iterator already having a ToArray override. But it's missing the Select case. This commit adds that, by copying the existing SelectArrayIterator and then just tweaking it to use _start/_end rather than accessing a stored _source array.

using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System; using System.Collections.Generic; using System.Linq;

[InProcess] [MemoryDiagnoser] public class Test { public static void Main() => BenchmarkRunner.Run();

[Params(1, 10, 100, 1000)]
public int Size { get; set; }

[Benchmark] public void RangeSelectIterate() { foreach (int item in Enumerable.Range(0, Size).Select(i => i)) { } }
[Benchmark] public int[] RangeSelectToArray() => Enumerable.Range(0, Size).Select(i => i).ToArray();
[Benchmark] public List<int> RangeSelectToList() => Enumerable.Range(0, Size).Select(i => i).ToList();

}

Method Size Mean Before Mean After Memory Before Memory After
RangeSelectIterate 1 83.65 ns 57.00 ns 96 B 88 B
RangeSelectToArray 1 72.15 ns 50.64 ns 128 B 120 B
RangeSelectToList 1 77.64 ns 58.61 ns 160 B 152 B
RangeSelectIterate 10 190.89 ns 123.68 ns 96 B 88 B
RangeSelectToArray 10 138.11 ns 71.17 ns 160 B 152 B
RangeSelectToList 10 151.71 ns 84.80 ns 192 B 184 B
RangeSelectIterate 100 1,136.12 ns 689.90 ns 96 B 88 B
RangeSelectToArray 100 741.59 ns 279.15 ns 520 B 512 B
RangeSelectToList 100 727.97 ns 336.18 ns 552 B 544 B
RangeSelectIterate 1000 10,603.56 ns 6,362.80 ns 96 B 88 B
RangeSelectToArray 1000 6,729.38 ns 2,371.04 ns 4120 B 4112 B
RangeSelectToList 1000 6,665.97 ns 2,799.10 ns 4152 B 4144 B

cc: @maryamariyan, @cston, @danmosemsft