diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
index f3a2c373d1872..fa0c354fdbcbc 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj
@@ -32,8 +32,7 @@
-
+
@@ -45,6 +44,7 @@
+
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs
index a1c6830a77e4c..346c5e56796c3 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs
@@ -1657,15 +1657,20 @@ public void CopyTo(Span destination)
}
///
- /// Sets the bytes in 'outBytes' to be random values. outBytes.Length must be less than or equal to 16
+ /// Sets the bytes in 'outBytes' to be random values. outBytes.Length must be either 8 or 16 bytes.
///
///
internal static unsafe void SetToRandomBytes(Span outBytes)
{
- Debug.Assert(outBytes.Length <= sizeof(Guid)); // Guid is 16 bytes, and so is TraceId
- Guid guid = Guid.NewGuid();
- ReadOnlySpan guidBytes = new ReadOnlySpan(&guid, sizeof(Guid));
- guidBytes.Slice(0, outBytes.Length).CopyTo(outBytes);
+ Debug.Assert(outBytes.Length == 16 || outBytes.Length == 8);
+ RandomNumberGenerator r = RandomNumberGenerator.Current;
+
+ Unsafe.WriteUnaligned(ref outBytes[0], r.Next());
+
+ if (outBytes.Length == 16)
+ {
+ Unsafe.WriteUnaligned(ref outBytes[8], r.Next());
+ }
}
///
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/RandomNumberGenerator.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/RandomNumberGenerator.cs
new file mode 100755
index 0000000000000..dd151339b5cf4
--- /dev/null
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/RandomNumberGenerator.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics
+{
+ ///
+ /// RandomNumberGenerator implementation is the 64-bit random number generator based on the Xoshiro256StarStar algorithm (known as shift-register generators).
+ ///
+ internal class RandomNumberGenerator
+ {
+ [ThreadStatic] private static RandomNumberGenerator? t_random;
+
+ private ulong _s0, _s1, _s2, _s3;
+
+ public static RandomNumberGenerator Current
+ {
+ get
+ {
+ if (t_random == null)
+ {
+ t_random = new RandomNumberGenerator();
+ }
+ return t_random;
+ }
+ }
+
+#if ALLOW_PARTIALLY_TRUSTED_CALLERS
+ [System.Security.SecuritySafeCriticalAttribute]
+#endif
+ public unsafe RandomNumberGenerator()
+ {
+ do
+ {
+ Guid g1 = Guid.NewGuid();
+ Guid g2 = Guid.NewGuid();
+ ulong* g1p = (ulong*)&g1;
+ ulong* g2p = (ulong*)&g2;
+ _s0 = *g1p;
+ _s1 = *(g1p + 1);
+ _s2 = *g2p;
+ _s3 = *(g2p + 1);
+
+ // Guid uses the 4 most significant bits of the first long as the version which would be fixed and not randomized.
+ // and uses 2 other bits in the second long for variants which would be fixed and not randomized too.
+ // let's overwrite the fixed bits in each long part by the other long.
+ _s0 = (_s0 & 0x0FFFFFFFFFFFFFFF) | (_s1 & 0xF000000000000000);
+ _s2 = (_s2 & 0x0FFFFFFFFFFFFFFF) | (_s3 & 0xF000000000000000);
+ _s1 = (_s1 & 0xFFFFFFFFFFFFFF3F) | (_s0 & 0x00000000000000C0);
+ _s3 = (_s3 & 0xFFFFFFFFFFFFFF3F) | (_s2 & 0x00000000000000C0);
+ }
+ while ((_s0 | _s1 | _s2 | _s3) == 0);
+ }
+
+ private ulong Rol64(ulong x, int k) => (x << k) | (x >> (64 - k));
+
+ public long Next()
+ {
+ ulong result = Rol64(_s1 * 5, 7) * 9;
+ ulong t = _s1 << 17;
+
+ _s2 ^= _s0;
+ _s3 ^= _s1;
+ _s1 ^= _s2;
+ _s0 ^= _s3;
+
+ _s2 ^= t;
+ _s3 = Rol64(_s3, 45);
+
+ return (long)result;
+ }
+ }
+}