Optimize Enumerable.Range(...).Select(...)#37410
Conversation
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. 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.
Add these to dotnet/performance? cc @adamsitnik, @billwert |
ahsonkhan
left a comment
There was a problem hiding this comment.
Some nits/questions, but looks like you are following the existing code patterns used in other iterators.
adamsitnik
left a comment
There was a problem hiding this comment.
LGTM, but I left some questions to get a better understanding.
|
Thanks for reviewing, @ahsonkhan and @adamsitnik. |
|
Does 'repeat.select' should be optimized also? |
|
I found very little usage of Repeat in general outside of test code, and very little of that used Select. What's the scenario where it's important that be a fast as possible? |
| public SelectRangeIterator(int start, int end, Func<int, TResult> selector) | ||
| { | ||
| Debug.Assert(start < end); | ||
| Debug.Assert((end - start) <= int.MaxValue); |
There was a problem hiding this comment.
This expression is always true,even overflow.
Does it should be?
Debug.Assert(unchecked((uint)(end - start) <= (uint)int.MaxValue));
There was a problem hiding this comment.
Yup, it's missing the casts. We'd welcome a PR if you'd like to fix it. Thanks.
* Optimize Enumerable.Range(...).Select(...) 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. 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. * Add more Debug.Asserts Commit migrated from dotnet/corefx@23f320b
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.
cc: @maryamariyan, @cston, @danmosemsft