-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Improve AppendLiteral for short literals #57217
Improve AppendLiteral for short literals #57217
Conversation
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
Seems like a good use case for #11484, which would allow us to say "pssst, JIT, I'd like this method to go down a different code path based on whether the caller is passing a const into this function." Then you get the best of both worlds: branch elimination for consts, and not including the switch at all for non-consts. /cc @AndyAyersMS |
src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs
Outdated
Show resolved
Hide resolved
The pattern |
Yes... is there a better option? |
Not that I'm aware of, if we're trying to be defensive against the possibility of pos being negative or int.MaxValue. |
src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs
Outdated
Show resolved
Hide resolved
df261dd
to
7e95f99
Compare
7e95f99
to
531e3bc
Compare
@SamMonoRT, this is failing a specific CodeDom test consistently with the mono interpreter. Is there someone who could help take a look? |
@BrzVlad - can you help with the failing interpreter tests ? |
531e3bc
to
66ab4bf
Compare
DefaultInterpolatedStringHandler.AppendLiteral is special, in that the 99.9% use case is it's called as part of string interpolation by compiler-generated code where the argument is always a literal. That means when the method is inlined, the JIT can specialize the implementation based on knowing the literal's Length is a constant. Which means we can provide specialized implementations for common lengths, resulting in faster and smaller code. This does so for strings of length 1 and 2, as they're quite common in code bases examined, and it does so for both the default handler and also the handler used to format into a span. The exact same code as before gets generated by the JIT for literals of length > 2. The main downside here is if someone does manually call this CompilerServices method with a variable, the call site will end up bloated with the special cases.
66ab4bf
to
c59e430
Compare
DefaultInterpolatedStringHandler.AppendLiteral is special, in that the 99.9% use case is it's called as part of string interpolation by compiler-generated code where the argument is always a literal. That means when the method is inlined, the JIT can specialize the implementation based on knowing the literal's Length is a constant. Which means we can provide specialized implementations for common lengths, resulting in faster and smaller code. This does so for strings of length 1 and 2, as they're quite common in code bases examined, and it does so for both the default handler and also the handler used to format into a span. Just as one data point, a quick-and-dirty search through dotnet/aspnetcore suggests that ~15% of literals are 1-character long.
The exact same code as before gets generated by the JIT for literals of length > 2 (well, at least for the default handler; for the TryWrite one, there's a few more instructions getting generated now for reasons I'm unsure of). The main downside here is if someone does manually call this CompilerServices method with a variable, the call site will end up bloated with the special cases.
cc: @GrabYourPitchforks, @EgorBo