Skip to content

Commit 4b8841e

Browse files
committed
Create a hot path for GetFloatingPointMaxDigitsAndPrecision
1 parent 26ce775 commit 4b8841e

File tree

1 file changed

+29
-29
lines changed

1 file changed

+29
-29
lines changed

src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -412,19 +412,34 @@ internal static unsafe void DecimalToNumber(scoped ref decimal d, ref NumberBuff
412412
number.CheckConsistency();
413413
}
414414

415+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
415416
private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int precision, NumberFormatInfo info, out bool isSignificantDigits)
416417
{
417-
if (fmt == 0)
418+
// We want to fast path the common case of no format and general format + precision.
419+
// These are commonly encountered and the full switch is otherwise large enough to show up in hot path profiles
420+
421+
fmt |= 0x20;
422+
423+
if ((fmt == 0x20) || (fmt == 'g'))
418424
{
425+
// The general format uses the precision specifier to indicate the number of significant
426+
// digits to format. This defaults to the shortest roundtrippable string. Additionally,
427+
// given that we can't return zero significant digits, we treat 0 as returning the shortest
428+
// roundtrippable string as well.
429+
419430
isSignificantDigits = true;
420-
return precision;
431+
return (precision == 0) ? -1 : precision;
421432
}
422433

423-
int maxDigits = precision;
434+
return Slow(fmt, ref precision, info, out isSignificantDigits);
424435

425-
switch (fmt | 0x20)
436+
static int Slow(char fmt, ref int precision, NumberFormatInfo info, out bool isSignificantDigits)
426437
{
427-
case 'c':
438+
int maxDigits = precision;
439+
440+
switch (fmt)
441+
{
442+
case 'c':
428443
{
429444
// The currency format uses the precision specifier to indicate the number of
430445
// decimal digits to format. This defaults to NumberFormatInfo.CurrencyDecimalDigits.
@@ -438,7 +453,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
438453
break;
439454
}
440455

441-
case 'e':
456+
case 'e':
442457
{
443458
// The exponential format uses the precision specifier to indicate the number of
444459
// decimal digits to format. This defaults to 6. However, the exponential format
@@ -456,8 +471,8 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
456471
break;
457472
}
458473

459-
case 'f':
460-
case 'n':
474+
case 'f':
475+
case 'n':
461476
{
462477
// The fixed-point and number formats use the precision specifier to indicate the number
463478
// of decimal digits to format. This defaults to NumberFormatInfo.NumberDecimalDigits.
@@ -471,23 +486,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
471486
break;
472487
}
473488

474-
case 'g':
475-
{
476-
// The general format uses the precision specifier to indicate the number of significant
477-
// digits to format. This defaults to the shortest roundtrippable string. Additionally,
478-
// given that we can't return zero significant digits, we treat 0 as returning the shortest
479-
// roundtrippable string as well.
480-
481-
if (precision == 0)
482-
{
483-
precision = -1;
484-
}
485-
isSignificantDigits = true;
486-
487-
break;
488-
}
489-
490-
case 'p':
489+
case 'p':
491490
{
492491
// The percent format uses the precision specifier to indicate the number of
493492
// decimal digits to format. This defaults to NumberFormatInfo.PercentDecimalDigits.
@@ -505,7 +504,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
505504
break;
506505
}
507506

508-
case 'r':
507+
case 'r':
509508
{
510509
// The roundtrip format ignores the precision specifier and always returns the shortest
511510
// roundtrippable string.
@@ -516,14 +515,15 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
516515
break;
517516
}
518517

519-
default:
518+
default:
520519
{
521520
ThrowHelper.ThrowFormatException_BadFormatSpecifier();
522521
goto case 'r'; // unreachable
523522
}
524-
}
523+
}
525524

526-
return maxDigits;
525+
return maxDigits;
526+
}
527527
}
528528

529529
public static string FormatFloat<TNumber>(TNumber value, string? format, NumberFormatInfo info)

0 commit comments

Comments
 (0)