-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Use CollectionsMarshal avoid additional bounds checks #27032
Conversation
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs
Outdated
Show resolved
Hide resolved
29906e7 to
e721a2e
Compare
|
Feedback addressed |
|
These unsafe or dangerous constructs should not be used just because of we can. Each use should be justified by measurable performance improvement. Does this make anything measurably faster? |
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
Outdated
Show resolved
Hide resolved
3f9d9c7 to
a8e0f9b
Compare
| lock (continuationList) { } | ||
|
|
||
| // Operate over Span to skip extra bounds check from using List | ||
| Span<object?> continuations = CollectionsMarshal.AsSpan(continuationList); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having more than one continuation is a rare path already. Is it really worth optimizing this? How many continuations the task needs to have to make this optimization measurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this instance; left in the swaps for List.Enumerable as the 2xsizeof(IntPtr) Span is smaller than the 3xsizeof(IntPtr) List.Enumerator and its foreach conversion to for(i<span.Length) is more efficient than the List's MoveNext+Current which additionally incurs version and additional bounds checks.
Is it really worth optimizing this?
Probably not significant relative to the continuations that are then triggered from .WaitAll; however my main motivation is: dotnet/corefx#41306 (review)
Also, presumably there are places we should be using this in corefx? I don't love adding API we can't/don't ourselves use.
Ideally; I'd find places where it has a significant impact, however I'm a little time constrained atm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These unsafe or dangerous constructs should not be used just because of we can. Each use should be justified by measurable performance improvement.
a8e0f9b to
f175a37
Compare
|
Thank you for your contribution. As announced in dotnet/coreclr#27549 this repository will be moving to dotnet/runtime on November 13. If you would like to continue working on this PR after this date, the easiest way to move the change to dotnet/runtime is:
|
|
Thank you for your contribution. As announced in #27549 the dotnet/runtime repository will be used going forward for changes to this code base. Closing this PR as no more changes will be accepted into master for this repository. If you’d like to continue working on this change please move it to dotnet/runtime. |
From dotnet/corefx#41306 (comment)
Using the enumerator for
List<T>of iterating in aforintroduces extra bounds checks as the length of the list is not the same as the length of the underlying array.Marshalling to a Span first gives a fast enumerator with no additional bounds checks, and no additional bounds checks in a regular
for; also can skip covarience checks.Mostly just using it in a few places to demonstrate usage; this isn't an exhaustive or hot-path search by any means.
/cc @stephentoub