Skip to content

Commit

Permalink
NewId changes
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison authored and phatboyg committed Feb 17, 2023
1 parent fd316e0 commit b876ed9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 67 deletions.
139 changes: 73 additions & 66 deletions src/MassTransit.Abstractions/NewId/NewId.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
namespace MassTransit
{
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;
using NewIdFormatters;
using NewIdProviders;
#if NET6_0_OR_GREATER
using System.Diagnostics;
using System.Runtime.Intrinsics.X86;
using System.Runtime.Intrinsics;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -51,19 +51,15 @@ public NewId(in byte[] bytes)
if (bytes.Length != 16)
throw new ArgumentException("Exactly 16 bytes expected", nameof(bytes));

FromByteArray(bytes, out _a, out _b, out _c, out _d);
FromByteArray(bytes, out this);
}

public NewId(in string value)
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("must not be null or empty", nameof(value));

var guid = new Guid(value);

var bytes = guid.ToByteArray();

FromByteArray(bytes, out _a, out _b, out _c, out _d);
FromGuid(new Guid(value), out this);
}

public NewId(int a, int b, int c, int d)
Expand Down Expand Up @@ -286,42 +282,14 @@ public Guid ToSequentialGuid()

public static NewId FromGuid(in Guid guid)
{
#if NET6_0_OR_GREATER
if (Ssse3.IsSupported && BitConverter.IsLittleEndian)
{
Span<Guid> span = stackalloc Guid[1];
span[0] = guid;
Span<byte> byteSpan = MemoryMarshal.Cast<Guid, byte>(span);

FromByteSpan(byteSpan, out var newId);
return newId;
}
#endif

var bytes = guid.ToByteArray();
FromByteArray(bytes, out var a, out var b, out var c, out var d);

return new NewId(a, b, c, d);
FromGuid(guid, out var newId);
return newId;
}

public static NewId FromSequentialGuid(in Guid guid)
{
#if NET6_0_OR_GREATER
if (Ssse3.IsSupported && BitConverter.IsLittleEndian)
{
Span<Guid> span = stackalloc Guid[1];
span[0] = guid;
Span<byte> byteSpan = MemoryMarshal.Cast<Guid, byte>(span);

FromSequentialByteSpan(byteSpan, out var newId);
return newId;
}
#endif

var bytes = guid.ToByteArray();
FromSequentialByteArray(bytes, out var a, out var b, out var c, out var d);

return new NewId(a, b, c, d);
FromSequentialByteArray(guid, out var newId);
return newId;
}

public byte[] ToByteArray()
Expand Down Expand Up @@ -535,47 +503,86 @@ public static Guid NextSequentialGuid()
return _getGenerator().NextSequentialGuid();
}

static void FromByteArray(in byte[] bytes, out int a, out int b, out int c, out int d)
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromGuid(in Guid guid, out NewId newId)
{
a = (bytes[10] << 24) | (bytes[11] << 16) | (bytes[12] << 8) | bytes[13];
b = (bytes[14] << 24) | (bytes[15] << 16) | (bytes[8] << 8) | bytes[9];
c = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | bytes[4];
d = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[0] << 8) | bytes[1];
Span<byte> bytes = stackalloc byte[16];
guid.TryWriteBytes(bytes);
FromByteArray(bytes, out newId);
}

#if NET6_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromByteSpan(ReadOnlySpan<byte> span, out NewId newId)
static void FromByteArray(ReadOnlySpan<byte> bytes, out NewId newId)
{
Debug.Assert(span.Length == Unsafe.SizeOf<Guid>());
Debug.Assert(Ssse3.IsSupported && BitConverter.IsLittleEndian);
#if NET6_0_OR_GREATER
if (Ssse3.IsSupported && BitConverter.IsLittleEndian)
{
var vector = MemoryMarshal.Read<Vector128<byte>>(bytes);
var shuffle = Vector128.Create((byte)13, 12, 11, 10, 9, 8, 15, 14, 4, 5, 6, 7, 1, 0, 2, 3);
Vector128<byte> result = Ssse3.Shuffle(vector, shuffle);
newId = Unsafe.As<Vector128<byte>, NewId>(ref result);
return;
}
#endif
var a = (bytes[10] << 24) | (bytes[11] << 16) | (bytes[12] << 8) | bytes[13];
var b = (bytes[14] << 24) | (bytes[15] << 16) | (bytes[8] << 8) | bytes[9];
var c = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | bytes[4];
var d = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[0] << 8) | bytes[1];

var vector = MemoryMarshal.Read<Vector128<byte>>(span);
var shuffle = Vector128.Create((byte)13, 12, 11, 10, 9, 8, 15, 14, 4, 5, 6, 7, 1, 0, 2, 3);
Vector128<byte> result = Ssse3.Shuffle(vector, shuffle);
newId = Unsafe.As<Vector128<byte>, NewId>(ref result);
newId = new NewId(a, b, c, d);
}
#endif

static void FromSequentialByteArray(in byte[] bytes, out int a, out int b, out int c, out int d)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromSequentialByteArray(in Guid guid, out NewId newId)
{
a = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
b = (bytes[5] << 24) | (bytes[4] << 16) | (bytes[7] << 8) | bytes[6];
c = (bytes[8] << 24) | (bytes[9] << 16) | (bytes[10] << 8) | bytes[11];
d = (bytes[12] << 24) | (bytes[13] << 16) | (bytes[14] << 8) | bytes[15];
Span<byte> bytes = stackalloc byte[16];
guid.TryWriteBytes(bytes);
#if NET6_0_OR_GREATER
if (Ssse3.IsSupported && BitConverter.IsLittleEndian)
{
var vector = MemoryMarshal.Read<Vector128<byte>>(bytes);
var shuffle = Vector128.Create((byte)0, 1, 2, 3, 6, 7, 4, 5, 11, 10, 9, 8, 15, 14, 13, 12);
Vector128<byte> result = Ssse3.Shuffle(vector, shuffle);
newId = Unsafe.As<Vector128<byte>, NewId>(ref result);
return;
}
#endif
var a = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
var b = (bytes[5] << 24) | (bytes[4] << 16) | (bytes[7] << 8) | bytes[6];
var c = (bytes[8] << 24) | (bytes[9] << 16) | (bytes[10] << 8) | bytes[11];
var d = (bytes[12] << 24) | (bytes[13] << 16) | (bytes[14] << 8) | bytes[15];

newId = new NewId(a, b, c, d);
}
#else
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromGuid(in Guid guid, out NewId newId)
{
FromByteArray(guid.ToByteArray(), out newId);
}

#if NET6_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromSequentialByteSpan(ReadOnlySpan<byte> span, out NewId newId)
static void FromByteArray(in byte[] bytes, out NewId newId)
{
Debug.Assert(span.Length == Unsafe.SizeOf<Guid>());
Debug.Assert(Ssse3.IsSupported && BitConverter.IsLittleEndian);
var a = (bytes[10] << 24) | (bytes[11] << 16) | (bytes[12] << 8) | bytes[13];
var b = (bytes[14] << 24) | (bytes[15] << 16) | (bytes[8] << 8) | bytes[9];
var c = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | bytes[4];
var d = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[0] << 8) | bytes[1];

newId = new NewId(a, b, c, d);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void FromSequentialByteArray(in Guid guid, out NewId newId)
{
var bytes = guid.ToByteArray();
var a = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
var b = (bytes[5] << 24) | (bytes[4] << 16) | (bytes[7] << 8) | bytes[6];
var c = (bytes[8] << 24) | (bytes[9] << 16) | (bytes[10] << 8) | bytes[11];
var d = (bytes[12] << 24) | (bytes[13] << 16) | (bytes[14] << 8) | bytes[15];

var vector = MemoryMarshal.Read<Vector128<byte>>(span);
var shuffle = Vector128.Create((byte)0, 1, 2, 3, 6, 7, 4, 5, 11, 10, 9, 8, 15, 14, 13, 12);
Vector128<byte> result = Ssse3.Shuffle(vector, shuffle);
newId = Unsafe.As<Vector128<byte>, NewId>(ref result);
newId = new NewId(a, b, c, d);
}
#endif
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;net7.0;netcoreapp3.1</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>MassTransit.BenchmarkConsole</PackageId>
<OutputType>Exe</OutputType>
Expand Down
8 changes: 8 additions & 0 deletions tests/MassTransit.BenchmarkConsole/NewIdBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ public Config()
AddJob(
Job.Default.WithEnvironmentVariable(new EnvironmentVariable("COMPlus_EnableSSE2", "0")).WithRuntime(CoreRuntime.Core60).AsDefault());

AddJob(
Job.Default.WithEnvironmentVariable(new EnvironmentVariable("COMPlus_EnableSSE2", "0")).WithRuntime(CoreRuntime.Core70));

// Run with intrinsics
AddJob(
Job.Default.WithRuntime(CoreRuntime.Core60));
AddJob(
Job.Default.WithRuntime(CoreRuntime.Core70));
AddJob(
Job.Default.WithRuntime(CoreRuntime.Core31));
}
}


[Config(typeof(Config))]
[MemoryDiagnoser(false)]
public class NewIdBenchmarks
Expand Down

0 comments on commit b876ed9

Please sign in to comment.