Skip to main content
formatting
Source Link
greybeard
  • 7.8k
  • 3
  • 21
  • 56

So after updating my source code it looks that it performs fast enough and allocates no memory. Here are benchmark for comparing the most popular methods of generating guidsGUIDs.

Runtime=.NET Core 3.0 Force=True Server=True

Runtime=.NET Core 3.0 Force=True Server=True

|                              Method |      Mean |    Error |   StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
|          SqlServerNewSequentialGuid |  38.69 ns | 0.787 ns | 1.643 ns |  1.00 |    0.00 | 0.0009 |     - |     - |      80 B |
|                       Guid_Standard |  61.44 ns | 0.665 ns | 0.622 ns |  1.60 |    0.06 |      - |     - |     - |         - |
|        NHibernate_GuidCombGenerator | 160.22 ns | 3.070 ns | 2.721 ns |  4.16 |    0.20 | 0.0012 |     - |     - |     104 B |
|                       Guid_Comb_New | 291.56 ns | 5.421 ns | 4.805 ns |  7.57 |    0.37 | 0.0010 |     - |     - |     104 B |
| EFCore_SequentialGuidValueGenerator |  82.04 ns | 1.623 ns | 1.667 ns |  2.13 |    0.11 | 0.0007 |     - |     - |      72 B |
|                           NewId_Lib |  78.93 ns | 1.150 ns | 1.076 ns |  2.05 |    0.09 |      - |     - |     - |         - |
|       NewSequentialGuid_PureNetCore |  70.28 ns | 1.332 ns | 1.481 ns |  1.81 |    0.08 |      - |     - |     - |         - |
MethodMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
SqlServerNewSequentialGuid38.69 ns0.787 ns1.643 ns1.000.000.0009--80 B
Guid_Standard61.44 ns0.665 ns0.622 ns1.600.06----
NHibernate_GuidCombGenerator160.22 ns3.070 ns2.721 ns4.160.200.0012--104 B
Guid_Comb_New291.56 ns5.421 ns4.805 ns7.570.370.0010--104 B
EFCore_SequentialGuidValueGenerator82.04 ns1.623 ns1.667 ns2.130.110.0007--72 B
NewId_Lib78.93 ns1.150 ns1.076 ns2.050.09----
NewSequentialGuid_PureNetCore70.28 ns1.332 ns1.481 ns1.810.08----

So after updating my source code it looks that it performs fast enough and allocates no memory. Here are benchmark for comparing the most popular methods of generating guids.

Runtime=.NET Core 3.0 Force=True Server=True

|                              Method |      Mean |    Error |   StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
|          SqlServerNewSequentialGuid |  38.69 ns | 0.787 ns | 1.643 ns |  1.00 |    0.00 | 0.0009 |     - |     - |      80 B |
|                       Guid_Standard |  61.44 ns | 0.665 ns | 0.622 ns |  1.60 |    0.06 |      - |     - |     - |         - |
|        NHibernate_GuidCombGenerator | 160.22 ns | 3.070 ns | 2.721 ns |  4.16 |    0.20 | 0.0012 |     - |     - |     104 B |
|                       Guid_Comb_New | 291.56 ns | 5.421 ns | 4.805 ns |  7.57 |    0.37 | 0.0010 |     - |     - |     104 B |
| EFCore_SequentialGuidValueGenerator |  82.04 ns | 1.623 ns | 1.667 ns |  2.13 |    0.11 | 0.0007 |     - |     - |      72 B |
|                           NewId_Lib |  78.93 ns | 1.150 ns | 1.076 ns |  2.05 |    0.09 |      - |     - |     - |         - |
|       NewSequentialGuid_PureNetCore |  70.28 ns | 1.332 ns | 1.481 ns |  1.81 |    0.08 |      - |     - |     - |         - |

So after updating my source code it looks that it performs fast enough and allocates no memory. Here are benchmark for comparing the most popular methods of generating GUIDs.

Runtime=.NET Core 3.0 Force=True Server=True

MethodMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
SqlServerNewSequentialGuid38.69 ns0.787 ns1.643 ns1.000.000.0009--80 B
Guid_Standard61.44 ns0.665 ns0.622 ns1.600.06----
NHibernate_GuidCombGenerator160.22 ns3.070 ns2.721 ns4.160.200.0012--104 B
Guid_Comb_New291.56 ns5.421 ns4.805 ns7.570.370.0010--104 B
EFCore_SequentialGuidValueGenerator82.04 ns1.623 ns1.667 ns2.130.110.0007--72 B
NewId_Lib78.93 ns1.150 ns1.076 ns2.050.09----
NewSequentialGuid_PureNetCore70.28 ns1.332 ns1.481 ns1.810.08----
MethodMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
SqlServerNewSequentialGuid38.69 ns0.787 ns1.643 ns1.000.000.0009--80 B
Guid_Standard61.44 ns0.665 ns0.622 ns1.600.06----
NHibernate_GuidCombGenerator160.22 ns3.070 ns2.721 ns4.160.200.0012--104 B
Guid_Comb_New291.56 ns5.421 ns4.805 ns7.570.370.0010--104 B
EFCore_SequentialGuidValueGenerator82.04 ns1.623 ns1.667 ns2.130.110.0007--72 B
NewId_Lib78.93 ns1.150 ns1.076 ns2.050.09----
NewSequentialGuid_PureNetCore70.28 ns1.332 ns1.481 ns1.810.08----
|                              Method |      Mean |    Error |   StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
|          SqlServerNewSequentialGuid |  38.69 ns | 0.787 ns | 1.643 ns |  1.00 |    0.00 | 0.0009 |     - |     - |      80 B |
|                       Guid_Standard |  61.44 ns | 0.665 ns | 0.622 ns |  1.60 |    0.06 |      - |     - |     - |         - |
|        NHibernate_GuidCombGenerator | 160.22 ns | 3.070 ns | 2.721 ns |  4.16 |    0.20 | 0.0012 |     - |     - |     104 B |
|                       Guid_Comb_New | 291.56 ns | 5.421 ns | 4.805 ns |  7.57 |    0.37 | 0.0010 |     - |     - |     104 B |
| EFCore_SequentialGuidValueGenerator |  82.04 ns | 1.623 ns | 1.667 ns |  2.13 |    0.11 | 0.0007 |     - |     - |      72 B |
|                           NewId_Lib |  78.93 ns | 1.150 ns | 1.076 ns |  2.05 |    0.09 |      - |     - |     - |         - |
|       NewSequentialGuid_PureNetCore |  70.28 ns | 1.332 ns | 1.481 ns |  1.81 |    0.08 |      - |     - |     - |         - |
using System;
using System.Buffers;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;

namespace PerfBenchmarkDotNet
{
    internal readonly struct FastGuid
    {
        private static readonly byte[] _macBytes;
        private static long _baseDateTicks;
        private static long _clockSequenceNumber;

        static FastGuid()
        {
            _clockSequenceNumber = 0;
            _macBytes = GetDefaultMacAdress();
            _baseDateTicks = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc).Ticks;
        }

        public static Guid NewGuid()
        {
            var nowTicks = DateTime.UtcNow.Ticks;
            var sequenceNumber = Interlocked.Increment(ref _clockSequenceNumber);
            var ticksDiff = nowTicks - _baseDateTicks;

            var a = (int)(ticksDiff);
            short b = (short)(ticksDiff >> 32);
            short c = (short)(ticksDiff >> 48);

            return new Guid(
                a,
                b,
                c,
                (byte)(sequenceNumber >> 8),
                (byte)(sequenceNumber),
                _macBytes[0],
                _macBytes[1],
                _macBytes[2],
                _macBytes[3],
                _macBytes[4],
                _macBytes[5]);
        }

        private static byte[] GetDefaultMacAdress()
        {
            var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();

            if (nic != null)
            {
                return nic.GetPhysicalAddress().GetAddressBytes();
            }

            var fallback = Guid.NewGuid().ToByteArray();
            return fallback.Take(6).ToArray();
        }
    }
}
using System;
using System.Buffers;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;

namespace PerfBenchmarkDotNet
{
    internal readonly struct FastGuid
    {
        private static readonly byte[] _macBytes;
        private static long _baseDateTicks;
        private static long _clockSequenceNumber;

        static FastGuid()
        {
            _clockSequenceNumber = 0;
            _macBytes = GetDefaultMacAdress();
            _baseDateTicks = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc).Ticks;
        }

        public static Guid NewGuid()
        {
            var nowTicks = DateTime.UtcNow.Ticks;
            var sequenceNumber = Interlocked.Increment(ref _clockSequenceNumber);
            var ticksDiff = nowTicks - _baseDateTicks;

            var a = (int)(ticksDiff);
            short b = (short)(ticksDiff >> 32);
            short c = (short)(ticksDiff >> 48);

            return new Guid(
                a,
                b,
                c,
                (byte)(sequenceNumber >> 8),
                (byte)(sequenceNumber),
                _macBytes[0],
                _macBytes[1],
                _macBytes[2],
                _macBytes[3],
                _macBytes[4],
                _macBytes[5]);
        }

        private static byte[] GetDefaultMacAdress()
        {
            var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();

            if (nic != null)
            {
                return nic.GetPhysicalAddress().GetAddressBytes();
            }

            var fallback = Guid.NewGuid().ToByteArray();
            return fallback.Take(6).ToArray();
        }
    }
}
MethodMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
SqlServerNewSequentialGuid38.69 ns0.787 ns1.643 ns1.000.000.0009--80 B
Guid_Standard61.44 ns0.665 ns0.622 ns1.600.06----
NHibernate_GuidCombGenerator160.22 ns3.070 ns2.721 ns4.160.200.0012--104 B
Guid_Comb_New291.56 ns5.421 ns4.805 ns7.570.370.0010--104 B
EFCore_SequentialGuidValueGenerator82.04 ns1.623 ns1.667 ns2.130.110.0007--72 B
NewId_Lib78.93 ns1.150 ns1.076 ns2.050.09----
NewSequentialGuid_PureNetCore70.28 ns1.332 ns1.481 ns1.810.08----
using System;
using System.Buffers;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;

namespace PerfBenchmarkDotNet
{
    internal readonly struct FastGuid
    {
        private static readonly byte[] _macBytes;
        private static long _baseDateTicks;
        private static long _clockSequenceNumber;

        static FastGuid()
        {
            _clockSequenceNumber = 0;
            _macBytes = GetDefaultMacAdress();
            _baseDateTicks = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc).Ticks;
        }

        public static Guid NewGuid()
        {
            var nowTicks = DateTime.UtcNow.Ticks;
            var sequenceNumber = Interlocked.Increment(ref _clockSequenceNumber);
            var ticksDiff = nowTicks - _baseDateTicks;

            var a = (int)(ticksDiff);
            short b = (short)(ticksDiff >> 32);
            short c = (short)(ticksDiff >> 48);

            return new Guid(
                a,
                b,
                c,
                (byte)(sequenceNumber >> 8),
                (byte)(sequenceNumber),
                _macBytes[0],
                _macBytes[1],
                _macBytes[2],
                _macBytes[3],
                _macBytes[4],
                _macBytes[5]);
        }

        private static byte[] GetDefaultMacAdress()
        {
            var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();

            if (nic != null)
            {
                return nic.GetPhysicalAddress().GetAddressBytes();
            }

            var fallback = Guid.NewGuid().ToByteArray();
            return fallback.Take(6).ToArray();
        }
    }
}
|                              Method |      Mean |    Error |   StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------------ |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
|          SqlServerNewSequentialGuid |  38.69 ns | 0.787 ns | 1.643 ns |  1.00 |    0.00 | 0.0009 |     - |     - |      80 B |
|                       Guid_Standard |  61.44 ns | 0.665 ns | 0.622 ns |  1.60 |    0.06 |      - |     - |     - |         - |
|        NHibernate_GuidCombGenerator | 160.22 ns | 3.070 ns | 2.721 ns |  4.16 |    0.20 | 0.0012 |     - |     - |     104 B |
|                       Guid_Comb_New | 291.56 ns | 5.421 ns | 4.805 ns |  7.57 |    0.37 | 0.0010 |     - |     - |     104 B |
| EFCore_SequentialGuidValueGenerator |  82.04 ns | 1.623 ns | 1.667 ns |  2.13 |    0.11 | 0.0007 |     - |     - |      72 B |
|                           NewId_Lib |  78.93 ns | 1.150 ns | 1.076 ns |  2.05 |    0.09 |      - |     - |     - |         - |
|       NewSequentialGuid_PureNetCore |  70.28 ns | 1.332 ns | 1.481 ns |  1.81 |    0.08 |      - |     - |     - |         - |
using System;
using System.Buffers;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;

namespace PerfBenchmarkDotNet
{
    internal readonly struct FastGuid
    {
        private static readonly byte[] _macBytes;
        private static long _baseDateTicks;
        private static long _clockSequenceNumber;

        static FastGuid()
        {
            _clockSequenceNumber = 0;
            _macBytes = GetDefaultMacAdress();
            _baseDateTicks = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc).Ticks;
        }

        public static Guid NewGuid()
        {
            var nowTicks = DateTime.UtcNow.Ticks;
            var sequenceNumber = Interlocked.Increment(ref _clockSequenceNumber);
            var ticksDiff = nowTicks - _baseDateTicks;

            var a = (int)(ticksDiff);
            short b = (short)(ticksDiff >> 32);
            short c = (short)(ticksDiff >> 48);

            return new Guid(
                a,
                b,
                c,
                (byte)(sequenceNumber >> 8),
                (byte)(sequenceNumber),
                _macBytes[0],
                _macBytes[1],
                _macBytes[2],
                _macBytes[3],
                _macBytes[4],
                _macBytes[5]);
        }

        private static byte[] GetDefaultMacAdress()
        {
            var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();

            if (nic != null)
            {
                return nic.GetPhysicalAddress().GetAddressBytes();
            }

            var fallback = Guid.NewGuid().ToByteArray();
            return fallback.Take(6).ToArray();
        }
    }
}
Source Link

So after updating my source code it looks that it performs fast enough and allocates no memory. Here are benchmark for comparing the most popular methods of generating guids.

Runtime=.NET Core 3.0 Force=True Server=True

Method Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
SqlServerNewSequentialGuid 38.69 ns 0.787 ns 1.643 ns 1.00 0.00 0.0009 - - 80 B
Guid_Standard 61.44 ns 0.665 ns 0.622 ns 1.60 0.06 - - - -
NHibernate_GuidCombGenerator 160.22 ns 3.070 ns 2.721 ns 4.16 0.20 0.0012 - - 104 B
Guid_Comb_New 291.56 ns 5.421 ns 4.805 ns 7.57 0.37 0.0010 - - 104 B
EFCore_SequentialGuidValueGenerator 82.04 ns 1.623 ns 1.667 ns 2.13 0.11 0.0007 - - 72 B
NewId_Lib 78.93 ns 1.150 ns 1.076 ns 2.05 0.09 - - - -
NewSequentialGuid_PureNetCore 70.28 ns 1.332 ns 1.481 ns 1.81 0.08 - - - -

Full source code in c# .net core 2.2+:

using System;
using System.Buffers;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;

namespace PerfBenchmarkDotNet
{
    internal readonly struct FastGuid
    {
        private static readonly byte[] _macBytes;
        private static long _baseDateTicks;
        private static long _clockSequenceNumber;

        static FastGuid()
        {
            _clockSequenceNumber = 0;
            _macBytes = GetDefaultMacAdress();
            _baseDateTicks = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc).Ticks;
        }

        public static Guid NewGuid()
        {
            var nowTicks = DateTime.UtcNow.Ticks;
            var sequenceNumber = Interlocked.Increment(ref _clockSequenceNumber);
            var ticksDiff = nowTicks - _baseDateTicks;

            var a = (int)(ticksDiff);
            short b = (short)(ticksDiff >> 32);
            short c = (short)(ticksDiff >> 48);

            return new Guid(
                a,
                b,
                c,
                (byte)(sequenceNumber >> 8),
                (byte)(sequenceNumber),
                _macBytes[0],
                _macBytes[1],
                _macBytes[2],
                _macBytes[3],
                _macBytes[4],
                _macBytes[5]);
        }

        private static byte[] GetDefaultMacAdress()
        {
            var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();

            if (nic != null)
            {
                return nic.GetPhysicalAddress().GetAddressBytes();
            }

            var fallback = Guid.NewGuid().ToByteArray();
            return fallback.Take(6).ToArray();
        }
    }
}