@@ -272,6 +272,35 @@ internal static partial class Number
272272
273273 // Optimizations using "TwoDigits" inspired by:
274274 // https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c/
275+ #if MONO
276+ // Workaround for a performance regression on Mono: https://github.com/dotnet/runtime/issues/111932
277+ private static readonly byte [ ] TwoDigitsCharsAsBytes =
278+ MemoryMarshal . AsBytes < char > ( "00010203040506070809" +
279+ "10111213141516171819" +
280+ "20212223242526272829" +
281+ "30313233343536373839" +
282+ "40414243444546474849" +
283+ "50515253545556575859" +
284+ "60616263646566676869" +
285+ "70717273747576777879" +
286+ "80818283848586878889" +
287+ "90919293949596979899" ) . ToArray ( ) ;
288+ private static readonly byte [ ] TwoDigitsBytes =
289+ ( "00010203040506070809"u8 +
290+ "10111213141516171819"u8 +
291+ "20212223242526272829"u8 +
292+ "30313233343536373839"u8 +
293+ "40414243444546474849"u8 +
294+ "50515253545556575859"u8 +
295+ "60616263646566676869"u8 +
296+ "70717273747576777879"u8 +
297+ "80818283848586878889"u8 +
298+ "90919293949596979899"u8 ) . ToArray ( ) ;
299+
300+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
301+ private static ref byte GetTwoDigitsBytesRef ( bool useChars ) =>
302+ ref MemoryMarshal . GetArrayDataReference ( useChars ? TwoDigitsCharsAsBytes : TwoDigitsBytes ) ;
303+ #else
275304 private static ReadOnlySpan < byte > TwoDigitsCharsAsBytes =>
276305 MemoryMarshal . AsBytes < char > ( "00010203040506070809" +
277306 "10111213141516171819" +
@@ -295,6 +324,12 @@ internal static partial class Number
295324 "80818283848586878889"u8 +
296325 "90919293949596979899"u8 ;
297326
327+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
328+ private static ref byte GetTwoDigitsBytesRef ( bool useChars ) =>
329+ ref MemoryMarshal . GetReference ( useChars ? TwoDigitsCharsAsBytes : TwoDigitsBytes ) ;
330+ #endif
331+
332+
298333 public static unsafe string FormatDecimal ( decimal value , ReadOnlySpan < char > format , NumberFormatInfo info )
299334 {
300335 char fmt = ParseFormatSpecifier ( format , out int digits ) ;
@@ -1572,7 +1607,7 @@ internal static unsafe void WriteTwoDigits<TChar>(uint value, TChar* ptr) where
15721607
15731608 Unsafe . CopyBlockUnaligned (
15741609 ref * ( byte * ) ptr ,
1575- ref Unsafe . Add ( ref MemoryMarshal . GetReference ( typeof ( TChar ) == typeof ( char ) ? TwoDigitsCharsAsBytes : TwoDigitsBytes ) , ( uint ) sizeof ( TChar ) * 2 * value ) ,
1610+ ref Unsafe . Add ( ref GetTwoDigitsBytesRef ( typeof ( TChar ) == typeof ( char ) ) , ( uint ) sizeof ( TChar ) * 2 * value ) ,
15761611 ( uint ) sizeof ( TChar ) * 2 ) ;
15771612 }
15781613
@@ -1588,7 +1623,7 @@ internal static unsafe void WriteFourDigits<TChar>(uint value, TChar* ptr) where
15881623
15891624 ( value , uint remainder ) = Math. DivRem ( value , 100 ) ;
15901625
1591- ref byte charsArray = ref MemoryMarshal . GetReference ( typeof ( TChar ) == typeof ( char ) ? TwoDigitsCharsAsBytes : TwoDigitsBytes ) ;
1626+ ref byte charsArray = ref GetTwoDigitsBytesRef ( typeof ( TChar ) == typeof ( char ) ) ;
15921627
15931628 Unsafe. CopyBlockUnaligned (
15941629 ref * ( byte * ) ptr ,
0 commit comments