diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index 1c66a341b0fde1..d8fbb261e4f381 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -300,6 +300,15 @@ public unsafe void Clear() [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Fill(T value) { + // Mono works faster with Unsafe.InitBlockUnaligned +#if MONO + if (sizeof(T) == 1) + { + Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _reference), *(byte*)&value, (uint)_length); + return; + } +#endif + SpanHelpers.Fill(ref _reference, (uint)_length, value); } diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs index 54294592099256..2a47b9437ecec2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs @@ -254,6 +254,13 @@ public static unsafe void ClearWithoutReferences(ref byte dest, nuint len) if (len == 0) return; + // Mono works faster with Unsafe.InitBlockUnaligned +#if MONO + if (len > ZeroMemoryNativeThreshold) + goto PInvoke; + Unsafe.InitBlockUnaligned(ref dest, 0, (uint)len); + return; +#else ref byte destEnd = ref Unsafe.Add(ref dest, len); if (len <= 16) @@ -427,6 +434,7 @@ public static unsafe void ClearWithoutReferences(ref byte dest, nuint len) Unsafe.WriteUnaligned(ref Unsafe.Add(ref destEnd, -4), 0); #endif return; +#endif // MONO PInvoke: // Implicit nullchecks @@ -498,24 +506,16 @@ internal static void Fill(ref byte dest, byte value, nuint len) nuint stopLoopAtOffset = len & ~(nuint)7; do { - Unsafe.Add(ref dest, (nint)i + 0) = value; - Unsafe.Add(ref dest, (nint)i + 1) = value; - Unsafe.Add(ref dest, (nint)i + 2) = value; - Unsafe.Add(ref dest, (nint)i + 3) = value; - Unsafe.Add(ref dest, (nint)i + 4) = value; - Unsafe.Add(ref dest, (nint)i + 5) = value; - Unsafe.Add(ref dest, (nint)i + 6) = value; - Unsafe.Add(ref dest, (nint)i + 7) = value; + // broadcast the value to all 8 bytes of the ulong and write it to memory + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, i), value * 0x101010101010101ul); } while ((i += 8) < stopLoopAtOffset); } // Write next 4 elements if needed if ((len & 4) != 0) { - Unsafe.Add(ref dest, (nint)i + 0) = value; - Unsafe.Add(ref dest, (nint)i + 1) = value; - Unsafe.Add(ref dest, (nint)i + 2) = value; - Unsafe.Add(ref dest, (nint)i + 3) = value; + // broadcast the value to all 4 bytes of the uint and write it to memory + Unsafe.WriteUnaligned(ref Unsafe.Add(ref dest, i), value * 0x1010101u); i += 4; }