Reducing list allocations and copying#11838
Conversation
c0f7e9e to
95fb602
Compare
| var index = (IndexExpression)_left; | ||
|
|
||
| var vars = new List<ParameterExpression>(index.ArgumentCount + 2); | ||
| var exprs = new List<Expression>(index.ArgumentCount + 3); |
There was a problem hiding this comment.
This is exactly the case that turns out to be more expensive than it should be. We know the size upfront, yet use a List<T> so we don't have to track an index into the array to assign to next (which is non-trivial due to the branching below). We then went on to pass the List<T> to the Block factory as-is, causing a copy to be made in its call to ToReadOnly. Given these collections exhibit ownership transfer behavior, we should be able to just create a TrueReadOnlyCollection<T> wrapper around a T[] and avoid any copies.
| if (NearestHoistedLocals != null && vars.Count > 0) | ||
| { | ||
| // Find what array each variable is on & its index | ||
| var indexes = new List<long>(vars.Count); |
There was a problem hiding this comment.
This turned out to be an unnecessary allocation when there are no variables. We created the list anyway and then went on to check the length of the list which gets populated in a loop with fixed iteration count and no conditionals inside, only to conclude it was throw-away work. Restructuring the conditionals here.
|
Test Innerloop Ubuntu14.04 Release Build and Test please (https://github.com/dotnet/corefx/issues/11851) |
|
LGTM. Can you rebase to address the merge conflict? |
95fb602 to
0311ed8
Compare
|
This is good to go now as well. |
|
Test Innerloop CentOS7.1 Release Build and Test please (failed to mkdirs) |
Reducing list allocations and copying Commit migrated from dotnet/corefx@8378243
This addresses issue #11837. In places where keeping track of the index of the next element to write into the array is rather clumsy, I'm using a small
ArrayBuilder<T>helper type which exposes anAddmethod, so the originalList<T>-like code keeps working and no index tracking is needed. This utility is also responsible to either return the array or return aTrueReadOnlyCollection<T>wrapping it (ownership transfer semantics), so we can pass it along to e.g. an expression factory method without causing it to create an unnecessary copy.