-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Don't emit frozen string literals for rare code paths #78370
Conversation
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsRyuJIT has a concept of string literals used in rare codepaths (think: the string literal with argument name when throwing My back-of-envelope calculation was suggesting we could save 20 kB for a hello world if we replace frozen string literals (that are fully laid out and aligned the way GC expects at runtime) with WTF-8 data strings that we hydrate into a Unfortunately, the actual size savings are mediocre - about 512 bytes to 1 kB on a Hello World, because accessing the lazy string literal requires quite a bit more code: static void Main(string[] args)
{
if (args.Length == 0)
throw new Exception("Lol");
Console.WriteLine("Lol");
}
Notice the extra 5 bytes for Still sending this out for people to have a look, but it's probably a dead end. Oh well. We could potentially change the helper to accept an integer index, but we will have trouble assigning integer indices to strings because the compiler is multithreaded and compiles methods in arbitrary orders (and we need outputs to be stable). Cc @dotnet/ilc-contrib
|
Are the working set savings (on Linux) more interesting? Frozen string literals need relocs. These lazy strings should not need relocs. |
Hm. what is the write barrier doing there? |
Do you have a scenario in mind that would be worth measuring? I guess it could help private working set a bit because we no longer need a reloc within the frozen object. We could potentially also introduce a cold data region where rarely used things like this could be placed. But on the other hand, the increase in code size will hurt working set until we do hot/cold splitting in NativeAOT.
I think it's setting the message field on the newed up exception object. |
It can be something as simple as |
Ah, right, it's just that in my branch |
Looks like it's doing worse. I added the call to the very beginning of the DynamicGenerics test and the numbers look like this for 5 runs (Linux x64 Release): Before:
After:
(I also tried the comparison for the "pointer compression" I have in the other pull request while I'm at it and that one doesn't seem to have an effect on working set, which is good and kind of expected based on my mental model. Of course it's still noisy but there's no big outliers like here.) |
We can revisit this after we have hot/cold splitting. |
RyuJIT has a concept of string literals used in rare codepaths (think: the string literal with argument name when throwing
ArgumentNullException
). Accessing these string literals doesn't have to be instant because we're going to do an expensive thing anyway. We didn't implement this before.My back-of-envelope calculation was suggesting we could save 20 kB for a hello world if we replace frozen string literals (that are fully laid out and aligned the way GC expects at runtime) with WTF-8 data strings that we hydrate into a
System.String
at runtime when they're needed.Unfortunately, the actual size savings are mediocre - about 512 bytes to 1 kB on a Hello World, because accessing the lazy string literal requires quite a bit more code:
Notice the extra 5 bytes for
call CORINFO_HELP_STRCNS_FROM_HANDLE
on top of thelea
.Still sending this out for people to have a look, but it's probably a dead end. Oh well.
We could potentially change the helper to accept an integer index, but we will have trouble assigning integer indices to strings because the compiler is multithreaded and compiles methods in arbitrary orders (and we need outputs to be stable).
Cc @dotnet/ilc-contrib