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

Implement IUtf8SpanFormattable on all the numeric types in corelib #84587

Merged
merged 4 commits into from
Apr 14, 2023

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented Apr 10, 2023

Augments SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Int128, UInt128, Half, Single, Double, NFloat, and Decimal to implement IUtf8SpanFormattable. Also fixes corelib TODOs around using IUtf8SpanFormattable. And removes some duplicate code from Utf8Formatter.

There is still more consolidation to be done between FormattingHelpers and Number.Formatting.

There are a few small (e.g. a few nanoseconds) regressions on my machine. I'm seeing what can be done about them. There are also some improvements. Most things are neutral.

For Utf8Formatter, most of the APIs are now just delegating into the corresponding IUtf8SpanFormattable functionality, which means things that weren't previously supported (e.g. various format specifiers) now are. I opted not to block them. We can revisit that decision if desired.

Fixes #84527
Contributes to #81500

@dotnet-issue-labeler
Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghost ghost assigned stephentoub Apr 10, 2023
@ghost
Copy link

ghost commented Apr 10, 2023

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

Augments SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Int128, UInt128, Half, Single, Double, NFloat, and Decimal to implement IUtf8SpanFormattable. Also fixes corelib TODOs around using IUtf8SpanFormattable. And removes some duplicate code from Utf8Formatter.

There is still more consolidation to be done between FormattingHelpers and Number.Formatting.

There are a few small (e.g. a few nanoseconds) regressions on my machine. I'm seeing what can be done about them. There are also some improvements. Most things are neutral.

For Utf8Formatter, most of the APIs are now just delegating into the corresponding IUtf8SpanFormattable functionality, which means things that weren't previously supported (e.g. various format specifiers) now are. I opted not to block them. We can revisit that decision if desired.

Author: stephentoub
Assignees: stephentoub
Labels:

area-System.Numerics, new-api-needs-documentation

Milestone: -

@stephentoub
Copy link
Member Author

I tried this on mono with the interpreter. Nothing concerning.

Type Method Toolchain value Mean Error StdDev Median Min Max Ratio
Perf_Int32 TryFormat \mono_main\corerun.exe -2147483648 333.06 ns 11.453 ns 13.190 ns 331.22 ns 314.15 ns 358.34 ns 1.00
Perf_Int32 TryFormat \mono_pr\corerun.exe -2147483648 353.11 ns 7.849 ns 8.724 ns 353.27 ns 334.36 ns 374.01 ns 1.06
Perf_Int64 TryFormat \mono_main\corerun.exe -9223372036854775808 466.66 ns 10.694 ns 11.443 ns 465.85 ns 450.36 ns 489.60 ns 1.00
Perf_Int64 TryFormat \mono_pr\corerun.exe -9223372036854775808 495.55 ns 10.122 ns 10.830 ns 498.20 ns 473.43 ns 512.00 ns 1.06
erf_UInt32 TryFormat \mono_main\corerun.exe 0 83.31 ns 2.288 ns 2.635 ns 83.67 ns 79.02 ns 88.41 ns 1.00
erf_UInt32 TryFormat \mono_pr\corerun.exe 0 82.20 ns 3.323 ns 3.693 ns 81.15 ns 77.34 ns 89.61 ns 0.99
erf_UInt64 TryFormat \mono_main\corerun.exe 0 92.51 ns 4.107 ns 4.565 ns 91.20 ns 85.58 ns 103.66 ns 1.00
erf_UInt64 TryFormat \mono_pr\corerun.exe 0 89.41 ns 3.055 ns 3.395 ns 89.44 ns 83.17 ns 96.26 ns 0.97
erf_UInt32 TryFormat \mono_main\corerun.exe 12345 139.30 ns 4.171 ns 4.803 ns 138.40 ns 132.78 ns 147.95 ns 1.00
erf_UInt32 TryFormat \mono_pr\corerun.exe 12345 137.93 ns 3.941 ns 4.380 ns 137.38 ns 128.94 ns 146.92 ns 0.99
erf_UInt64 TryFormat \mono_main\corerun.exe 12345 159.92 ns 6.865 ns 7.345 ns 158.78 ns 144.79 ns 176.94 ns 1.00
erf_UInt64 TryFormat \mono_pr\corerun.exe 12345 145.79 ns 3.228 ns 2.862 ns 145.82 ns 141.48 ns 151.74 ns 0.93
Perf_Int64 TryFormat \mono_main\corerun.exe 12345 160.28 ns 6.158 ns 6.589 ns 161.06 ns 149.81 ns 171.88 ns 1.00
Perf_Int64 TryFormat \mono_pr\corerun.exe 12345 154.55 ns 6.471 ns 7.452 ns 154.05 ns 143.41 ns 169.00 ns 0.97
Perf_Int32 TryFormat \mono_main\corerun.exe 12345 144.92 ns 6.497 ns 7.221 ns 143.31 ns 135.26 ns 159.17 ns 1.00
Perf_Int32 TryFormat \mono_pr\corerun.exe 12345 138.33 ns 3.083 ns 3.166 ns 138.08 ns 133.32 ns 143.43 ns 0.95
erf_UInt64 TryFormat \mono_main\corerun.exe 18446744073709551615 355.06 ns 6.491 ns 6.665 ns 356.68 ns 340.70 ns 368.52 ns 1.00
erf_UInt64 TryFormat \mono_pr\corerun.exe 18446744073709551615 360.70 ns 10.168 ns 11.709 ns 358.06 ns 342.45 ns 379.72 ns 1.01
Perf_Int32 TryFormat \mono_main\corerun.exe 4 90.05 ns 4.477 ns 5.155 ns 88.40 ns 84.18 ns 99.88 ns 1.00
Perf_Int32 TryFormat \mono_pr\corerun.exe 4 85.59 ns 2.724 ns 3.028 ns 85.27 ns 81.89 ns 92.78 ns 0.95
Perf_Int32 TryFormat \mono_main\corerun.exe 2147483647 204.16 ns 4.180 ns 3.491 ns 205.49 ns 197.97 ns 208.25 ns 1.00
Perf_Int32 TryFormat \mono_pr\corerun.exe 2147483647 203.92 ns 4.319 ns 4.242 ns 203.68 ns 196.28 ns 211.56 ns 1.00
erf_UInt32 TryFormat \mono_main\corerun.exe 4294967295 206.10 ns 5.729 ns 6.368 ns 204.80 ns 196.46 ns 217.24 ns 1.00
erf_UInt32 TryFormat \mono_pr\corerun.exe 4294967295 205.14 ns 8.239 ns 9.489 ns 204.53 ns 193.23 ns 225.89 ns 1.00
Perf_Int64 TryFormat \mono_main\corerun.exe 9223372036854775807 361.05 ns 9.419 ns 10.469 ns 360.48 ns 341.60 ns 380.22 ns 1.00
Perf_Int64 TryFormat \mono_pr\corerun.exe 9223372036854775807 375.84 ns 21.032 ns 22.504 ns 372.10 ns 343.07 ns 417.22 ns 1.04

Augments SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Int128, UInt128, Half, Single, Double, NFloat, and Decimal.

Also fixes corelib TODOs around using IUtf8SpanFormattable.

And removes some duplicate code from Utf8Formatter.

There is still more consolidation to be done between FormattingHelpers and Number.Formatting.
- Use an internal interface implemented by char and byte to have dedicated CastFrom methods that are always inlineable due to very small size.
- Use pointers in some core formatting routines to avoid needing bulky IL for manipulating refs with spans, making various members more inlineable.
- Avoid Encoding.UTF8.GetBytes in various code paths by caching more UTF8 sequences on DateTimeFormatInfo and NumberFormatInfo
- Change FormatCustomizedTimeZone to special-case 2 vs 3+ tokens in order to avoid extra AppendSpan calls
- Fix growth logic in ValueListBuilder to not forcibly grow more than is needed
- Inline ValueListBuilder.AppendSpan and remove some bounds checks (at least on 64-bit)
- Change FormatDigits to special-case lengths of 1/2/4 and to use existing formatting routines rather than a custom one
- Remove the FormatDigits wrapper overload and just have all calls go to the main workhorse method.
- Remove the use of "..."u8 in R/O formatting that leads to needing to use additional span-based helpers.  The minimal gain on coreclr isn't worth the extra complication
- Changed some switches to include half the cases based on lowercasing the ASCII input char
- Moved Date/TimeOnly charsWritten into Try method to be closer to the source of truth rather than having the value far aware (this isn't for perf and could possibly even be a microregression, so I included it here to ensure it's not measurable).
@stephentoub
Copy link
Member Author

The second commit here tries to address some of the regressions seen on some platforms in CI after the DateTime change went in. I did it in this PR in order to then be able to measure the end-to-end, as this PR was also modifying some of those code paths. Details on the changes made are in the second commit description. After merging this, we'll want to rebase @tannergooding's parsing PR in order to unify the interfaces introduced; Tanner, I can do that if you'd prefer, or you're of course welcome to.

Locally, here's what I see now comparing main to this pr...

On coreclr:

Namespace Type Method Job Toolchain format culturestring value Mean Error StdDev Median Min Max Ratio RatioSD Gen0 Allocated Alloc Ratio
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-DKFVDX \main\corerun.exe ? ? ? 290.99 ns 2.692 ns 2.248 ns 291.03 ns 286.66 ns 293.97 ns 1.00 0.00 0.0400 256 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-HQOKZW \pr\corerun.exe ? ? ? 264.81 ns 6.742 ns 7.214 ns 263.03 ns 256.78 ns 283.77 ns 0.91 0.03 0.0398 256 B 1.00
System.Tests Perf_DateTime ToString Job-DKFVDX \main\corerun.exe ? ? ? 187.16 ns 0.773 ns 0.723 ns 187.05 ns 185.93 ns 188.60 ns 1.00 0.00 0.0099 64 B 1.00
System.Tests Perf_DateTime ToString Job-HQOKZW \pr\corerun.exe ? ? ? 148.32 ns 2.036 ns 1.805 ns 147.99 ns 144.46 ns 151.34 ns 0.79 0.01 0.0100 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe ? ? ? 204.07 ns 2.620 ns 2.451 ns 204.08 ns 199.85 ns 209.01 ns 1.00 0.00 0.0124 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe ? ? ? 163.97 ns 2.053 ns 1.920 ns 163.89 ns 159.78 ns 167.18 ns 0.80 0.01 0.0126 80 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-DKFVDX \main\corerun.exe ? ? 170.91 ns 2.753 ns 2.576 ns 171.77 ns 167.48 ns 175.72 ns 1.00 0.00 0.0097 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQOKZW \pr\corerun.exe ? ? 125.04 ns 1.522 ns 1.424 ns 125.14 ns 122.02 ns 127.00 ns 0.73 0.01 0.0101 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 223.34 ns 3.561 ns 3.331 ns 223.44 ns 218.51 ns 229.03 ns 1.00 0.00 0.0127 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 176.15 ns 3.358 ns 3.449 ns 175.56 ns 171.74 ns 181.60 ns 0.79 0.02 0.0124 80 B 1.00
System.Tests Perf_DateTime ToString Job-DKFVDX \main\corerun.exe G ? ? 186.44 ns 1.500 ns 1.330 ns 186.14 ns 184.95 ns 188.92 ns 1.00 0.00 0.0098 64 B 1.00
System.Tests Perf_DateTime ToString Job-HQOKZW \pr\corerun.exe G ? ? 146.35 ns 2.501 ns 2.340 ns 146.73 ns 142.24 ns 149.91 ns 0.78 0.01 0.0100 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe G ? ? 189.00 ns 3.764 ns 3.143 ns 189.63 ns 182.86 ns 194.70 ns 1.00 0.00 0.0095 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe G ? ? 154.19 ns 0.598 ns 0.467 ns 154.24 ns 153.46 ns 155.11 ns 0.82 0.01 0.0102 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-DKFVDX \main\corerun.exe ? da ? 143.25 ns 1.448 ns 1.284 ns 143.30 ns 140.86 ns 145.29 ns 1.00 0.00 0.0101 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQOKZW \pr\corerun.exe ? da ? 112.09 ns 2.139 ns 2.001 ns 112.22 ns 108.70 ns 115.19 ns 0.78 0.02 0.0101 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-DKFVDX \main\corerun.exe ? fr ? 167.32 ns 1.175 ns 1.042 ns 167.50 ns 165.40 ns 168.69 ns 1.00 0.00 0.0101 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQOKZW \pr\corerun.exe ? fr ? 122.05 ns 2.218 ns 1.966 ns 121.48 ns 119.61 ns 126.93 ns 0.73 0.01 0.0101 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-DKFVDX \main\corerun.exe ? ja ? 172.88 ns 4.161 ns 4.274 ns 173.12 ns 165.59 ns 181.27 ns 1.00 0.00 0.0102 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQOKZW \pr\corerun.exe ? ja ? 122.76 ns 0.331 ns 0.258 ns 122.75 ns 122.28 ns 123.16 ns 0.71 0.02 0.0100 64 B 1.00
System.Tests Perf_DateTime ToString Job-DKFVDX \main\corerun.exe o ? ? 35.81 ns 0.783 ns 0.732 ns 35.86 ns 34.46 ns 36.96 ns 1.00 0.00 0.0127 80 B 1.00
System.Tests Perf_DateTime ToString Job-HQOKZW \pr\corerun.exe o ? ? 34.51 ns 2.081 ns 2.396 ns 33.86 ns 32.05 ns 40.23 ns 0.95 0.06 0.0127 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe o ? ? 43.17 ns 0.411 ns 0.384 ns 43.10 ns 42.58 ns 43.71 ns 1.00 0.00 0.0140 88 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe o ? ? 40.50 ns 0.573 ns 0.447 ns 40.61 ns 39.62 ns 41.06 ns 0.94 0.01 0.0139 88 B 1.00
System.Tests Perf_DateTime ToString Job-DKFVDX \main\corerun.exe r ? ? 26.59 ns 0.130 ns 0.116 ns 26.60 ns 26.35 ns 26.74 ns 1.00 0.00 0.0127 80 B 1.00
System.Tests Perf_DateTime ToString Job-HQOKZW \pr\corerun.exe r ? ? 23.19 ns 0.527 ns 0.586 ns 23.40 ns 22.25 ns 24.16 ns 0.88 0.02 0.0127 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe r ? ? 34.48 ns 0.596 ns 0.466 ns 34.46 ns 33.51 ns 35.30 ns 1.00 0.00 0.0127 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe r ? ? 36.62 ns 0.616 ns 0.576 ns 36.35 ns 35.93 ns 37.63 ns 1.06 0.02 0.0127 80 B 1.00
System.Tests Perf_DateTime ToString Job-DKFVDX \main\corerun.exe s ? ? 170.36 ns 2.486 ns 2.204 ns 170.29 ns 167.40 ns 174.70 ns 1.00 0.00 0.0096 64 B 1.00
System.Tests Perf_DateTime ToString Job-HQOKZW \pr\corerun.exe s ? ? 135.22 ns 1.681 ns 1.572 ns 135.62 ns 131.86 ns 137.13 ns 0.79 0.01 0.0100 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-DKFVDX \main\corerun.exe s ? ? 173.64 ns 3.014 ns 2.820 ns 172.97 ns 169.09 ns 177.67 ns 1.00 0.00 0.0101 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQOKZW \pr\corerun.exe s ? ? 142.35 ns 1.513 ns 1.263 ns 142.00 ns 141.14 ns 144.96 ns 0.82 0.01 0.0098 64 B 1.00

On mono with JIT:

Namespace Type Method Job Toolchain format culturestring value Mean Error StdDev Median Min Max Ratio Gen0 Allocated Alloc Ratio
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-MSNEDZ \mono_main\corerun.exe ? ? ? 1,050.68 ns 3.527 ns 3.299 ns 1,050.26 ns 1,045.72 ns 1,056.89 ns 1.00 0.0588 256 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-IUCTIA \mono_pr\corerun.exe ? ? ? 937.77 ns 2.267 ns 2.010 ns 937.64 ns 934.16 ns 940.80 ns 0.89 0.0609 256 B 1.00
System.Tests Perf_DateTime ToString Job-MSNEDZ \mono_main\corerun.exe ? ? ? 620.09 ns 6.900 ns 6.454 ns 622.50 ns 603.54 ns 628.92 ns 1.00 0.0149 64 B 1.00
System.Tests Perf_DateTime ToString Job-IUCTIA \mono_pr\corerun.exe ? ? ? 432.00 ns 1.556 ns 1.379 ns 432.09 ns 429.82 ns 434.12 ns 0.70 0.0154 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe ? ? ? 698.02 ns 11.343 ns 8.856 ns 698.26 ns 681.19 ns 710.91 ns 1.00 0.0190 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe ? ? ? 486.29 ns 9.375 ns 8.769 ns 485.18 ns 472.73 ns 500.40 ns 0.70 0.0180 80 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-MSNEDZ \mono_main\corerun.exe ? ? 568.40 ns 0.739 ns 0.692 ns 568.46 ns 566.66 ns 569.58 ns 1.00 0.0137 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-IUCTIA \mono_pr\corerun.exe ? ? 356.10 ns 0.899 ns 0.750 ns 356.08 ns 355.06 ns 357.91 ns 0.63 0.0142 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 692.03 ns 5.552 ns 5.193 ns 692.34 ns 683.31 ns 699.70 ns 1.00 0.0168 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 536.38 ns 7.220 ns 6.753 ns 537.49 ns 527.05 ns 547.24 ns 0.78 0.0186 80 B 1.00
System.Tests Perf_DateTime ToString Job-MSNEDZ \mono_main\corerun.exe G ? ? 628.03 ns 2.549 ns 2.384 ns 627.85 ns 624.70 ns 632.96 ns 1.00 0.0150 64 B 1.00
System.Tests Perf_DateTime ToString Job-IUCTIA \mono_pr\corerun.exe G ? ? 428.02 ns 1.541 ns 1.287 ns 427.96 ns 426.38 ns 430.31 ns 0.68 0.0138 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe G ? ? 610.60 ns 4.548 ns 4.254 ns 609.90 ns 605.27 ns 618.87 ns 1.00 0.0150 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe G ? ? 438.45 ns 6.206 ns 5.501 ns 439.29 ns 426.91 ns 445.55 ns 0.72 0.0139 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-MSNEDZ \mono_main\corerun.exe ? da ? 477.16 ns 1.551 ns 1.451 ns 476.97 ns 474.89 ns 480.07 ns 1.00 0.0153 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-IUCTIA \mono_pr\corerun.exe ? da ? 310.78 ns 1.116 ns 0.989 ns 310.69 ns 309.12 ns 312.66 ns 0.65 0.0151 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-MSNEDZ \mono_main\corerun.exe ? fr ? 570.36 ns 5.445 ns 4.827 ns 568.28 ns 565.92 ns 581.29 ns 1.00 0.0137 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-IUCTIA \mono_pr\corerun.exe ? fr ? 359.30 ns 1.460 ns 1.295 ns 359.39 ns 356.14 ns 360.76 ns 0.63 0.0145 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-MSNEDZ \mono_main\corerun.exe ? ja ? 564.15 ns 2.491 ns 2.208 ns 563.45 ns 561.90 ns 569.41 ns 1.00 0.0135 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-IUCTIA \mono_pr\corerun.exe ? ja ? 355.88 ns 1.909 ns 1.692 ns 355.94 ns 353.62 ns 358.74 ns 0.63 0.0142 64 B 1.00
System.Tests Perf_DateTime ToString Job-MSNEDZ \mono_main\corerun.exe o ? ? 182.32 ns 2.430 ns 2.273 ns 183.42 ns 178.43 ns 184.97 ns 1.00 0.0185 80 B 1.00
System.Tests Perf_DateTime ToString Job-IUCTIA \mono_pr\corerun.exe o ? ? 123.78 ns 2.119 ns 1.982 ns 123.68 ns 119.99 ns 126.99 ns 0.68 0.0187 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe o ? ? 229.23 ns 2.548 ns 2.384 ns 229.70 ns 223.30 ns 232.40 ns 1.00 0.0208 88 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe o ? ? 157.22 ns 2.015 ns 1.884 ns 157.52 ns 153.84 ns 159.84 ns 0.69 0.0208 88 B 1.00
System.Tests Perf_DateTime ToString Job-MSNEDZ \mono_main\corerun.exe r ? ? 178.13 ns 2.514 ns 2.351 ns 177.67 ns 174.49 ns 181.56 ns 1.00 0.0188 80 B 1.00
System.Tests Perf_DateTime ToString Job-IUCTIA \mono_pr\corerun.exe r ? ? 88.46 ns 0.982 ns 0.918 ns 88.56 ns 86.98 ns 90.20 ns 0.50 0.0191 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe r ? ? 191.76 ns 2.290 ns 2.142 ns 192.25 ns 187.12 ns 194.69 ns 1.00 0.0188 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe r ? ? 103.36 ns 1.579 ns 1.477 ns 103.23 ns 100.91 ns 106.08 ns 0.54 0.0191 80 B 1.00
System.Tests Perf_DateTime ToString Job-MSNEDZ \mono_main\corerun.exe s ? ? 516.87 ns 2.666 ns 2.493 ns 516.78 ns 511.47 ns 521.04 ns 1.00 0.0143 64 B 1.00
System.Tests Perf_DateTime ToString Job-IUCTIA \mono_pr\corerun.exe s ? ? 348.59 ns 3.376 ns 3.158 ns 348.69 ns 342.47 ns 353.97 ns 0.67 0.0153 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-MSNEDZ \mono_main\corerun.exe s ? ? 526.78 ns 5.089 ns 4.249 ns 527.41 ns 516.41 ns 532.80 ns 1.00 0.0147 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-IUCTIA \mono_pr\corerun.exe s ? ? 368.76 ns 6.352 ns 5.942 ns 369.59 ns 357.03 ns 378.29 ns 0.70 0.0147 64 B 1.00

On mono with interpreter:

Namespace Type Method Job Toolchain format culturestring value Mean Error StdDev Median Min Max Ratio RatioSD Gen0 Allocated Alloc Ratio
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-HQABMR \mono_main\corerun.exe ? ? ? 6,398.6 ns 270.25 ns 311.22 ns 6,334.9 ns 5,914.3 ns 7,079.0 ns 1.00 0.00 0.0492 256 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToStringHebrewIsrael Job-OMVXSP \mono_pr\corerun.exe ? ? ? 5,559.5 ns 273.88 ns 315.40 ns 5,544.5 ns 5,030.0 ns 6,133.7 ns 0.87 0.07 0.0426 256 B 1.00
System.Tests Perf_DateTime ToString Job-HQABMR \mono_main\corerun.exe ? ? ? 3,581.3 ns 133.81 ns 148.73 ns 3,585.3 ns 3,309.1 ns 3,897.3 ns 1.00 0.00 0.0145 64 B 1.00
System.Tests Perf_DateTime ToString Job-OMVXSP \mono_pr\corerun.exe ? ? ? 3,008.7 ns 145.33 ns 167.36 ns 3,010.8 ns 2,725.6 ns 3,345.5 ns 0.84 0.05 0.0122 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe ? ? ? 4,328.7 ns 168.00 ns 179.75 ns 4,284.1 ns 4,128.0 ns 4,787.6 ns 1.00 0.00 0.0173 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe ? ? ? 3,573.2 ns 89.15 ns 102.66 ns 3,567.9 ns 3,339.0 ns 3,747.6 ns 0.83 0.04 0.0141 80 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQABMR \mono_main\corerun.exe ? ? 3,383.1 ns 139.93 ns 155.53 ns 3,396.2 ns 3,165.2 ns 3,619.8 ns 1.00 0.00 0.0137 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-OMVXSP \mono_pr\corerun.exe ? ? 2,518.1 ns 131.51 ns 151.44 ns 2,500.0 ns 2,207.7 ns 2,869.9 ns 0.75 0.04 0.0093 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 4,264.2 ns 105.33 ns 121.29 ns 4,267.9 ns 4,064.0 ns 4,512.9 ns 1.00 0.00 0.0166 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe ? ? 12/30/2017 3:45:22 AM -08:00 3,939.1 ns 92.48 ns 102.79 ns 3,961.2 ns 3,658.9 ns 4,072.1 ns 0.92 0.03 0.0158 80 B 1.00
System.Tests Perf_DateTime ToString Job-HQABMR \mono_main\corerun.exe G ? ? 3,501.4 ns 121.44 ns 139.86 ns 3,465.7 ns 3,277.7 ns 3,847.5 ns 1.00 0.00 0.0140 64 B 1.00
System.Tests Perf_DateTime ToString Job-OMVXSP \mono_pr\corerun.exe G ? ? 2,843.8 ns 54.48 ns 53.51 ns 2,854.3 ns 2,730.1 ns 2,947.6 ns 0.81 0.04 0.0114 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe G ? ? 3,795.0 ns 127.23 ns 141.42 ns 3,785.6 ns 3,489.2 ns 4,130.1 ns 1.00 0.00 0.0148 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe G ? ? 3,138.6 ns 108.11 ns 124.50 ns 3,151.6 ns 2,889.3 ns 3,327.0 ns 0.83 0.05 0.0124 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQABMR \mono_main\corerun.exe ? da ? 2,737.7 ns 94.59 ns 101.21 ns 2,735.0 ns 2,583.0 ns 2,939.4 ns 1.00 0.00 0.0107 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-OMVXSP \mono_pr\corerun.exe ? da ? 2,046.2 ns 79.62 ns 88.50 ns 2,043.6 ns 1,884.4 ns 2,218.1 ns 0.74 0.04 0.0082 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQABMR \mono_main\corerun.exe ? fr ? 3,310.2 ns 153.47 ns 176.73 ns 3,283.7 ns 3,079.1 ns 3,726.7 ns 1.00 0.00 0.0125 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-OMVXSP \mono_pr\corerun.exe ? fr ? 2,351.7 ns 58.65 ns 67.55 ns 2,348.2 ns 2,209.2 ns 2,457.0 ns 0.71 0.04 0.0092 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-HQABMR \mono_main\corerun.exe ? ja ? 3,331.4 ns 98.20 ns 105.07 ns 3,330.2 ns 3,169.6 ns 3,503.6 ns 1.00 0.00 0.0133 64 B 1.00
System.Globalization.Tests Perf_DateTimeCultureInfo ToString Job-OMVXSP \mono_pr\corerun.exe ? ja ? 2,426.2 ns 112.57 ns 129.64 ns 2,422.6 ns 2,239.1 ns 2,777.1 ns 0.73 0.04 0.0100 64 B 1.00
System.Tests Perf_DateTime ToString Job-HQABMR \mono_main\corerun.exe o ? ? 620.7 ns 13.93 ns 15.48 ns 617.1 ns 596.5 ns 651.5 ns 1.00 0.00 0.0178 80 B 1.00
System.Tests Perf_DateTime ToString Job-OMVXSP \mono_pr\corerun.exe o ? ? 574.4 ns 24.51 ns 28.22 ns 569.9 ns 536.8 ns 632.1 ns 0.92 0.05 0.0189 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe o ? ? 853.1 ns 22.35 ns 25.74 ns 845.8 ns 818.8 ns 895.9 ns 1.00 0.00 0.0200 88 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe o ? ? 780.9 ns 23.09 ns 26.59 ns 777.2 ns 743.3 ns 840.5 ns 0.92 0.04 0.0193 88 B 1.00
System.Tests Perf_DateTime ToString Job-HQABMR \mono_main\corerun.exe r ? ? 499.7 ns 15.03 ns 17.31 ns 494.2 ns 471.9 ns 535.3 ns 1.00 0.00 0.0182 80 B 1.00
System.Tests Perf_DateTime ToString Job-OMVXSP \mono_pr\corerun.exe r ? ? 407.5 ns 13.84 ns 15.94 ns 404.9 ns 383.0 ns 429.7 ns 0.82 0.03 0.0188 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe r ? ? 718.7 ns 31.72 ns 36.52 ns 714.0 ns 670.6 ns 797.6 ns 1.00 0.00 0.0170 80 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe r ? ? 573.2 ns 12.35 ns 14.22 ns 576.7 ns 546.9 ns 595.1 ns 0.80 0.05 0.0172 80 B 1.00
System.Tests Perf_DateTime ToString Job-HQABMR \mono_main\corerun.exe s ? ? 2,940.7 ns 97.15 ns 107.98 ns 2,935.1 ns 2,791.9 ns 3,154.7 ns 1.00 0.00 0.0115 64 B 1.00
System.Tests Perf_DateTime ToString Job-OMVXSP \mono_pr\corerun.exe s ? ? 2,340.8 ns 87.63 ns 100.91 ns 2,330.2 ns 2,194.2 ns 2,557.5 ns 0.80 0.04 0.0085 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-HQABMR \mono_main\corerun.exe s ? ? 3,036.9 ns 85.21 ns 98.13 ns 3,031.1 ns 2,846.5 ns 3,220.8 ns 1.00 0.00 0.0113 64 B 1.00
System.Tests Perf_DateTimeOffset ToString Job-OMVXSP \mono_pr\corerun.exe s ? ? 2,497.2 ns 96.26 ns 110.85 ns 2,454.4 ns 2,365.4 ns 2,771.7 ns 0.82 0.04 0.0094 64 B 1.00

Note that all of these numbers are based on commit 7526a4c, and thus all include fixes @vargaz already made in response to this issue (279c65a, 8699942, and ae4c82b).

@lewing
Copy link
Member

lewing commented Apr 13, 2023

@BrzVlad @kg can you take a look at the failures here they seem interpreter specific

@kg
Copy link
Member

kg commented Apr 13, 2023

@BrzVlad @kg can you take a look at the failures here they seem interpreter specific

The failures for browser-wasm interp and mono_interpreter linux look of the same kind, so I think if jiterp is involved it's correctly emulating interp behavior here. Happy to help look into it once I get time if Vlad is too busy though, and if the interp gets changed I can update the jiterp to match.

@vargaz
Copy link
Contributor

vargaz commented Apr 13, 2023

The failures appear to be some kind of memory corruption when running with the interpreter. Testcase:

using System;
using System.Threading.Tasks;
using System.Buffers;
using System.Buffers.Text;
using System.Text;
using System.Globalization;

public class Test
{
    public static void Main () {
        string standardFormat = "o";
        var r = new Random(42);
        for (int i = 0; i < 200; i++) {
            DateTime dt = new DateTime(DateTime.MinValue.Ticks + (long)(r.NextDouble() * (DateTime.MaxValue.Ticks - DateTime.MinValue.Ticks)), DateTimeKind.Unspecified);
            string expected = dt.ToString(standardFormat);

            Console.WriteLine (expected);
            DateTime.ParseExact(expected, standardFormat, null).ToString(standardFormat);
            DateTime.ParseExact(expected, standardFormat, null, DateTimeStyles.None).ToString(standardFormat);
            DateTime.ParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.None).ToString(standardFormat);
            DateTime.ParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.AllowWhiteSpaces).ToString(standardFormat);

            DateTime.TryParseExact(expected, standardFormat, null, DateTimeStyles.None, out DateTime actual);
            DateTime.TryParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.None, out actual);
            actual.ToString (standardFormat);
            DateTime.Parse(expected);
        }
    }
}

@kg
Copy link
Member

kg commented Apr 13, 2023

The failures appear to be some kind of memory corruption when running with the interpreter. Testcase:

using System;
using System.Threading.Tasks;
using System.Buffers;
using System.Buffers.Text;
using System.Text;
using System.Globalization;

public class Test
{
    public static void Main () {
        string standardFormat = "o";
        var r = new Random(42);
        for (int i = 0; i < 200; i++) {
            DateTime dt = new DateTime(DateTime.MinValue.Ticks + (long)(r.NextDouble() * (DateTime.MaxValue.Ticks - DateTime.MinValue.Ticks)), DateTimeKind.Unspecified);
            string expected = dt.ToString(standardFormat);

            Console.WriteLine (expected);
            DateTime.ParseExact(expected, standardFormat, null).ToString(standardFormat);
            DateTime.ParseExact(expected, standardFormat, null, DateTimeStyles.None).ToString(standardFormat);
            DateTime.ParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.None).ToString(standardFormat);
            DateTime.ParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.AllowWhiteSpaces).ToString(standardFormat);

            DateTime.TryParseExact(expected, standardFormat, null, DateTimeStyles.None, out DateTime actual);
            DateTime.TryParseExact(expected, new[] { standardFormat }, null, DateTimeStyles.None, out actual);
            actual.ToString (standardFormat);
            DateTime.Parse(expected);
        }
    }
}

This repro works fine in debug wasm builds but fails in release, so it's likely an interpreter optimization problem.

@kg
Copy link
Member

kg commented Apr 13, 2023

If I remove all the '#if MONO' stuff in the Number.Formatting file, everything works fine.

@vargaz
Copy link
Contributor

vargaz commented Apr 14, 2023

For the record, the mono failures are caused by the #if MONO block in WriteFourDigits. Running the interpreter with
--interp=-inline seems to fix the problem.

@stephentoub
Copy link
Member Author

For the record, the mono failures are caused by the #if MONO block in WriteFourDigits. Running the interpreter with
--interp=-inline seems to fix the problem.

Thanks. I've removed those blocks, but we obviously should also sepatately figure out what the issue is in the interpreter.

Copy link
Member

@tannergooding tannergooding left a comment

Choose a reason for hiding this comment

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

LGTM.

Are you going to switch the APIs to be public in a follow up PR?

@stephentoub
Copy link
Member Author

stephentoub commented Apr 14, 2023

Are you going to switch the APIs to be public in a follow up PR?

Yup.

LGTM.

Thanks.

@stephentoub stephentoub merged commit ed09ae5 into dotnet:main Apr 14, 2023
@stephentoub stephentoub deleted the numericsutf8 branch April 14, 2023 13:35
@ghost ghost locked as resolved and limited conversation to collaborators May 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use primitive type IUtf8SpanFormattable implementations
8 participants