Skip to content
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

Use RuntimeHelpers.CreateSpan for array initialization with relevant primitives #61414

Merged
merged 12 commits into from
Dec 5, 2022

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented May 19, 2022

The compiler currently optimizes array creation where:

  • The array is immediately stored as a ReadOnlySpan<T> such that it's not exposed in any writeable manner
  • The array is initialized entirely with constant values
  • The element type is a single byte primitive (byte, bool, sbyte)

In such a situation, it creates a PrivateImplementationDetails field containing the data, and replaces the array creation with a span that points directly to the data on PrivateImplementationDetails.

This PR extends that optimization to multi-byte primitives: short, ushort, char, int, uint, long, ulong, float, and double. If the target platform has the RuntimeHelpers.CreateSpan method, it is used to handle endianness fixups. If the target platform lacks that method, the compiler emits code to cache the array in PrivateImplementationDetails and wrap a span around that lazily-initialized array.

@stephentoub stephentoub force-pushed the usecreatespan branch 2 times, most recently from 669693c to f2575fe Compare May 29, 2022 00:09
@AlekseyTs
Copy link
Contributor

@stephentoub We discourage force pushes and any forms of rewriting existing commits in branches that are already under review process. These operations confuse CodeFlow (the tool that we usually use for reviews) and prevent us from doing reviews in an incremental fashion. That is forcing us to start the review process from scratch after a change like that is performed. The recommended process is to keep pushing new commits into the branch, including merge commits, until PR is ready for merge, then doing a squash merge.

@stephentoub
Copy link
Member Author

including merge commits

Most of the code this touches had to be rewritten in the face of the conflicting commit that got merged. I don't believe the effort required to review with a rebase or a merge would have been significantly different. But I will try to refrain from rebases in the future.

@MichalPetryka
Copy link

MichalPetryka commented May 31, 2022

Would be nice if ReadOnlySpan<char> span = "text"; would also be optimized, since it's a much more convenient syntax for strings and would be analogous to the utf8 string feature.

@stephentoub
Copy link
Member Author

stephentoub commented May 31, 2022

Would be nice if ReadOnlySpan span = "text"; would also be optimized, since it's a much more convenient syntax for strings and would be analogous to the utf8 string feature.

What is it you'd hope it would do it's not already doing?
SharpLab

@MichalPetryka
Copy link

Would be nice if ReadOnlySpan span = "text"; would also be optimized, since it's a much more convenient syntax for strings and would be analogous to the utf8 string feature.

What is it you'd hope it would do it's not already doing? SharpLab

I thought the runtime materialized the string and created a span over it then, but it seems I was wrong despite the IL using ldstr.

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 2), new tests are not reviewed.

@AlekseyTs
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 4 pipeline(s).

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 11)

@stephentoub
Copy link
Member Author

Ok. Let's go without regression test for this scenario. Based on code review, the current behavior should be as expected.

Great, thanks.

@stephentoub
Copy link
Member Author

Feedback addressed, thanks.

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 12)

@AlekseyTs
Copy link
Contributor

@jcouv Please review the latest revision

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks (iteration 12)

@jcouv jcouv merged commit 7a8b78e into dotnet:main Dec 5, 2022
@ghost ghost added this to the Next milestone Dec 5, 2022
@jcouv
Copy link
Member

jcouv commented Dec 5, 2022

Thanks @stephentoub :-)

@stephentoub
Copy link
Member Author

Thank you, both, for the reviews.

@stephentoub stephentoub deleted the usecreatespan branch December 5, 2022 20:07
@EgorBo
Copy link
Member

EgorBo commented Dec 5, 2022

Looking forward to seeing a huge PR against dotnet/runtime to replace all arrays with ROS<> for primitive types other than byte 😄

@stephentoub
Copy link
Member Author

I have it ready to go, we just need the new compiler to flow in :)

@codemonkey85
Copy link

FYI, it looks like this change doesn't work in Blazor WebAssembly. I think it's an issue with Mono? I created a sample solution to show that it works in a Console app, and not in a Blazor WASM app: https://github.com/codemonkey85/BlazorWasmIssueWithArrayInitializationWithRelevantPrimitives

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.