new List<T>(IEnumrable<T>) & List<T>.AddRange(IEnumerable<T>) doesn't use IIListProvider. #98845
-
Discussed in #98773Originally posted by ActivistInvestor February 21, 2024 After looking at the source and doing a simple test, I want to be sure that there's nothing wrong with my testing methodology, because I'm seeing much better performance from
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 10 replies
-
LINQ's operators feed information between them using internal interfaces. When you do runtime/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs Lines 219 to 225 in 15ff723 runtime/src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs Lines 227 to 233 in 15ff723 In contrast, List<T> , which is lower in the stack, knows nothing about the internal types used by LINQ to implement these operators: all it knows is it was given an IEnumerable<T> that it needs to enumerate. And while it does look for ICollection<T> on the type to use as an optimization, that internal SelectRangeIterator type from LINQ doesn't and can't implement ICollection<T> , and thus List<T> is forced to enumerate. The result is that, for this particular input, is thus comparing apples and oranges. If instead of:
var seq = Enumerable.Range(0, 100000).Select(i => i / 2); you used this: var seq = CreateInput(0, 100000, i => i / 2);
...
static IEnumerable<int> CreateInput(int start, int count, Func<int, int> func)
{
int end = start + count;
for (int i = start; i < end; i++) yield return func(i);
} I expect you'd find that (As an aside, it's generally better to use a tool like benchmarkdotnet to do these kinds of measurements, rather than the approach taken above.) |
Beta Was this translation helpful? Give feedback.
-
Thanks for your comments and insight
I believe that enumeration is always required if the source is not a collection, but I was focusing on the optimization of allocating the storage for the result (allocating space for the entire result in a single operation, verses incrementally growing the capacity as needed). I tried your suggestion and here's what I get. I'll investigate further using BenchmarkDotNet when time permits:
|
Beta Was this translation helpful? Give feedback.
-
Tagging subscribers to this area: @dotnet/area-system-linq Issue DetailsDiscussed in #98773Originally posted by ActivistInvestor February 21, 2024 After looking at the source and doing a simple test, I want to be sure that there's nothing wrong with my testing methodology, because I'm seeing much better performance from
|
Beta Was this translation helpful? Give feedback.
No, I didn't. I said that ToList and new List would be comparable when using an iterator as the input.