-
-
Save MarkPflug/ddcac942c4934a4f7492411bbb9f9e24 to your computer and use it in GitHub Desktop.
Demonstration of Guid.CreateVersion7() behavior
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Microsoft.Data.SqlClient; | |
| using System.Runtime.InteropServices; | |
| using System.Runtime.Intrinsics; | |
| static class Program | |
| { | |
| public static int Main() | |
| { | |
| var connStr = | |
| new SqlConnectionStringBuilder(Environment.GetEnvironmentVariable("MSSqlConnStr")) | |
| { | |
| InitialCatalog = "Test" | |
| }; | |
| var conn = new SqlConnection(connStr.ConnectionString); | |
| conn.Open(); | |
| var cmd = conn.CreateCommand(); | |
| cmd.CommandText = | |
| """ | |
| create table GuidOrder ( | |
| guid uniqueidentifier not null, | |
| seq int not null, | |
| constraint PK_GuidOrder primary key (guid) | |
| ) | |
| """; | |
| // cmd.ExecuteNonQuery(); | |
| cmd.CommandText = "insert into GuidOrder (guid, seq) values (@guid, @seq)"; | |
| var guidParam = cmd.CreateParameter(); | |
| guidParam.ParameterName = "guid"; | |
| guidParam.SqlDbType = System.Data.SqlDbType.UniqueIdentifier; | |
| var seqParam = cmd.CreateParameter(); | |
| seqParam.ParameterName = "seq"; | |
| seqParam.SqlDbType = System.Data.SqlDbType.Int; | |
| cmd.Parameters.Add(guidParam); | |
| cmd.Parameters.Add(seqParam); | |
| for (int i = 0; i < 1000; i++) | |
| { | |
| //guidParam.Value = Guid.CreateVersion7(); | |
| guidParam.Value = Guid.NewSequentialGuid(); | |
| seqParam.Value = i; | |
| cmd.ExecuteNonQuery(); | |
| } | |
| cmd.Parameters.Clear(); | |
| cmd.CommandText = "select guid, seq from GuidOrder order by guid"; | |
| using var r = cmd.ExecuteReader(); | |
| var last = int.MinValue; | |
| while (r.Read()) | |
| { | |
| var id = r.GetInt32(1); | |
| if (id < last) | |
| { | |
| Console.WriteLine("FAILED"); | |
| return -1; | |
| } | |
| last = id; | |
| } | |
| Console.WriteLine("SUCCESS"); | |
| return 0; | |
| } | |
| } | |
| public static class GuidExtensions | |
| { | |
| static readonly Vector128<byte> Shuffle = Vector128.Create((byte)3, 2, 1, 0, 5, 4, 7, 6, 9, 8, 16, 14, 13, 12, 11, 10); | |
| static unsafe Guid ShuffleFast(Guid g) | |
| { | |
| var v = Vector128.Load((byte*)&g); | |
| v = Vector128.Shuffle(v, Shuffle); | |
| var span = AsSpan(ref g); | |
| Vector128.CopyTo(v, span); | |
| return g; | |
| } | |
| static Span<byte> AsSpan(ref Guid g) | |
| { | |
| Span<Guid> valSpan = MemoryMarshal.CreateSpan(ref g, 1); | |
| return MemoryMarshal.AsBytes(valSpan); | |
| } | |
| [DllImport("rpcrt4.dll", SetLastError = true)] | |
| static extern int UuidCreateSequential(out Guid guid); | |
| extension(Guid) | |
| { | |
| public static Guid NewSequentialGuid() | |
| { | |
| Guid g; | |
| UuidCreateSequential(out g); | |
| if (Vector128<byte>.IsSupported) | |
| { | |
| return ShuffleFast(g); | |
| } | |
| else | |
| { | |
| var a = AsSpan(ref g); | |
| var t = default(Guid); | |
| var b = AsSpan(ref t); | |
| b[10] = a[15]; | |
| b[11] = a[14]; | |
| b[12] = a[13]; | |
| b[13] = a[12]; | |
| b[14] = a[11]; | |
| b[15] = a[10]; | |
| b[8] = a[9]; | |
| b[9] = a[8]; | |
| b[6] = a[7]; | |
| b[7] = a[6]; | |
| b[4] = a[5]; | |
| b[5] = a[4]; | |
| b[0] = a[3]; | |
| b[1] = a[2]; | |
| b[2] = a[1]; | |
| b[3] = a[0]; | |
| return t; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment