-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize CollectionsMarshal.AsSpan
with inlining and bounds check removal
#56773
Comments
Tagging subscribers to this area: @GrabYourPitchforks, @dotnet/area-system-memory Issue DetailsDescriptionCurrently
Both issues could be easily solved, first one by applying The result would look like this: [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(List<T> list)
=> list is null ? default : MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(list._items), list._size); Optimizing it would be especially helpful in cases like #54999 where the operation performed on the span is simple and most likely AsSpan takes most of the time there. ConfigurationSharpLab Core CLR 5.0.721.25508 on amd64, since the code is the same on master the issue is most likely also there. Regression?Afaik AsSpan wasn't changed since its introduction, so no. DataSharplab comparing current and proposed implementation
|
This could create a Span longer than the array if the list was modified from a different thread. Afaik the concerns around the method were that the array could change under you, but this would bring in more unsafety. Maybe that's fine given it's under |
How would the current implementation prevent from that? @GrabYourPitchforks do you have any objections for using |
The With The returned span could now be longer than the array it is wrapping, pointing into arbitrary memory.
If you violated the thread safety before, you could get an exception. Now you could be corrupting memory. |
@MihaZupan thanks! In such a case, we should not change it. |
This is correct. In general, we want to avoid optimizations that convert "I corrupted the state of a single instance" into "I corrupted the state of the entire application." We've rejected such changes before. See #47186 and dotnet/corefx#39173 (comment) (#30141). I feel we shouldn't take this change. |
What about the AggressiveInlining? |
I suppose it could instead be written with an extra T[] array = list._items;
return MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(array), (int)Math.Min((uint)array.Length, (uint)list._size)); Adds a few bytes but avoids corruption. This would also avoid the exception race. |
This is also an invalid optimization, especially if the The point of the |
@MichalPetryka thank you for your proposal and for creating an issue before sending a PR (this is very rare here ;) ) Since one of the proposed changes is not safe and another should not be an issue as this method should never be on a hot path, I am closing the issue. |
Description
Currently
CollectionsMarshal.AsSpan
has 2 big codegen issues:Both issues could be easily solved, first one by applying
[MethodImpl(MethodImplOptions.AggressiveInlining)]
on the method and the second one by replacingnew Span<T>(list._items, 0, list._size)
withMemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(list._items), list._size)
.The result would look like this:
Optimizing it would be especially helpful in cases like #54999 where the operation performed on the span is simple and most likely AsSpan takes most of the time there.
Configuration
SharpLab Core CLR 5.0.721.25508 on amd64, since the code is the same on main the issue is most likely also there.
Regression?
Afaik AsSpan wasn't changed since its introduction, so no.
Data
Sharplab comparing current and proposed implementation
The text was updated successfully, but these errors were encountered: