11using System ;
2+ using System . Diagnostics ;
23using NHibernate . Engine ;
34
45namespace NHibernate . Id
@@ -36,21 +37,50 @@ public partial class GuidCombGenerator : IIdentifierGenerator
3637 /// <returns>The new identifier as a <see cref="Guid"/>.</returns>
3738 public object Generate ( ISessionImplementor session , object obj )
3839 {
39- return GenerateComb ( ) ;
40+ return GenerateComb ( Guid . NewGuid ( ) , DateTime . UtcNow ) ;
4041 }
4142
4243 /// <summary>
4344 /// Generate a new <see cref="Guid"/> using the comb algorithm.
4445 /// </summary>
45- private Guid GenerateComb ( )
46+ protected static Guid GenerateComb ( in Guid guid , DateTime utcNow )
4647 {
47- byte [ ] guidArray = Guid . NewGuid ( ) . ToByteArray ( ) ;
48+ #if NET8_0_OR_GREATER
49+ Span < byte > guidArray = stackalloc byte [ 16 ] ;
50+ Span < byte > msecsArray = stackalloc byte [ sizeof ( long ) ] ;
51+ Span < byte > daysArray = stackalloc byte [ sizeof ( int ) ] ;
4852
49- DateTime now = DateTime . UtcNow ;
53+ var bytesWritten = guid . TryWriteBytes ( guidArray ) ;
54+ Debug . Assert ( bytesWritten ) ;
5055
5156 // Get the days and milliseconds which will be used to build the byte string
52- TimeSpan days = new TimeSpan ( now . Ticks - BaseDateTicks ) ;
53- TimeSpan msecs = now . TimeOfDay ;
57+ TimeSpan days = new TimeSpan ( utcNow . Ticks - BaseDateTicks ) ;
58+ TimeSpan msecs = utcNow . TimeOfDay ;
59+
60+ // Convert to a byte array
61+ // Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
62+
63+ bytesWritten = BitConverter . TryWriteBytes ( daysArray , days . Days )
64+ && BitConverter . TryWriteBytes ( msecsArray , ( long ) ( msecs . TotalMilliseconds / 3.333333 ) ) ;
65+ Debug . Assert ( bytesWritten ) ;
66+
67+ msecsArray . Reverse ( ) ;
68+
69+ // Copy the bytes into the guid
70+ //Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
71+ guidArray [ 10 ] = daysArray [ 1 ] ;
72+ guidArray [ 11 ] = daysArray [ 0 ] ;
73+
74+ //Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);
75+ msecsArray [ ^ 4 ..] . CopyTo ( guidArray [ ^ 4 ..] ) ;
76+ return new Guid ( guidArray ) ;
77+ #else
78+
79+ byte [ ] guidArray = guid . ToByteArray ( ) ;
80+
81+ // Get the days and milliseconds which will be used to build the byte string
82+ TimeSpan days = new TimeSpan ( utcNow . Ticks - BaseDateTicks ) ;
83+ TimeSpan msecs = utcNow . TimeOfDay ;
5484
5585 // Convert to a byte array
5686 // Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
@@ -66,6 +96,7 @@ private Guid GenerateComb()
6696 Array . Copy ( msecsArray , msecsArray . Length - 4 , guidArray , guidArray . Length - 4 , 4 ) ;
6797
6898 return new Guid ( guidArray ) ;
99+ #endif
69100 }
70101
71102 #endregion
0 commit comments