// From a discussion on mastodon https://mastodon.social/@antonz@c.im/112620103070756332 // This version: // * simplifies the setup (an inline array is already a Span) // * uses BinaryPrimitives.ReverseEndianness to batch writing the long to the buffer // * uses SkipLocalsInit on the ctor to avoid some zero init // Should be ~ 15% faster than the revised version with Span // Anyway most of the time is spent in DateTimeOffset.UtcNow and RandomNumberGenerator.Fill using System.Buffers.Binary; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Cryptography; public readonly struct UUIDv7Fast { private readonly InteriorStruct _interior; [SkipLocalsInit] public UUIDv7Fast() { long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); Unsafe.As(ref _interior) = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(timestamp << 16) : timestamp << 16; Span value = _interior; RandomNumberGenerator.Fill(value.Slice(6)); // version and variant value[6] = (byte)((value[6] & 0x0F) | 0x70); value[8] = (byte)((value[8] & 0x3F) | 0x80); } public byte[] GetBytes() => ((ReadOnlySpan)_interior).ToArray(); public void CopyTo(Span destination) => ((ReadOnlySpan)_interior).CopyTo(destination); public override string ToString() => Convert.ToHexString(_interior); public override int GetHashCode() { HashCode hc = new(); hc.AddBytes(_interior); return hc.ToHashCode(); } [InlineArray(16)] private struct InteriorStruct { private byte _element; } }