Conversation
- Make the fast path for Number.FormatXX & Number.TryFormatXX inlineable - Make parameterless ToString in SByte, Int16, Int32, and Int64 directly invoke the default formatting method - Consolidate Number.FormatX & Number.TryFormatX code
src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
Outdated
Show resolved
Hide resolved
|
|
||
| public static unsafe string FormatInt32(int value, ReadOnlySpan<char> format, IFormatProvider? provider) | ||
| /// <summary> | ||
| /// This interface lets us use shared implementations (FormatInt and TryFormatInt) |
There was a problem hiding this comment.
It is true the code in the steady state is going to be almost identical. There is extra overhead in the size of runtime generics control structures. My back of the envelope calculation says that it is 10kB - 20kB (once all integer formatting routines are used).
@marek-safar How do you feel about the trade-offs in this implementation for mobile and web-assembly (footprint-sensitive targets)?
The technique that can be used to eliminate the generics overhead, while keeping the code shared, is generating the code using .tt template. We use it for SIMD types: https://github.com/dotnet/runtime/tree/master/src/libraries/System.Private.CoreLib/src/System/Numerics . It does not look as pretty, but gets the job done. Thoughts about whether it would be worth doing it in this case?
There was a problem hiding this comment.
The formating code is already casing troubles when linking, introducing more interface abstraction will make the matter worse. It's not a large amount of code but it's quite likely we'll need to redo the formating code to be linker friendly.
Although the numbers look good for JIT we should not overoptimize for JIT and make e.g. AOT slower. What is the perf impact on AOT?
There was a problem hiding this comment.
The formating code is already causing troubles when linking
Can you share details?
There was a problem hiding this comment.
I don't have precise data at hand as we are still working on the tooling but the fact is that the formatting code is a large chunk of any app (minimal amount code is linked out for formatting)
There was a problem hiding this comment.
Thanks. I thought you were saying it's worse on core than it was previously on mono; that's not the case, right?
There was a problem hiding this comment.
I don't have the exact data to confirm that but my guess would be that it should not differ significantly between mono and netcore (in a negative or positive way) at the moment.
There was a problem hiding this comment.
System.Private.CoreLib.dll R2R image size is 9,203,200 before this change and 9,213,440 after this change (Win x64 release). This size delta is not the entire overhead - there is also extra private memory at runtime. It would be nice to reduce it.
jkotas
left a comment
There was a problem hiding this comment.
LGTM (module the open question about whether the generics footprint is acceptable).
Thank you for doing this! The improvements for the default case are very nice.
stephentoub
left a comment
There was a problem hiding this comment.
Both the perf improvement and the code reduction are nice. I agree it looks good subject to a decision around the generic expansions.
|
There are really two independent changes in this PR. It may be a good idea to split this into 2 PRs to make forward progress:
|
👍 |
|
We are fine with the code duplication here. Adding generics to save a couple hundred lines is not a good tradeoff for the runtime footprint as discussed above. Thank you for giving this a try! |
I'm including the benchmark results below for only Perf_Int32.ToString and Perf_Int32.ToStringHex, as I think they adequately demonstrate the impact of the changes.