Skip to content

Instantly share code, notes, and snippets.

@ifle
Last active August 30, 2019 10:17
Show Gist options
  • Save ifle/9328949346d1a616d115f3642ec08e79 to your computer and use it in GitHub Desktop.
Save ifle/9328949346d1a616d115f3642ec08e79 to your computer and use it in GitHub Desktop.
using System;
using System.Threading;
namespace Common
{
/// <summary>
/// Inspired by <see href="https://github.com/aspnet/AspNetCore/blob/master/src/Servers/Kestrel/shared/CorrelationIdGenerator.cs"/>,
/// this class generates an efficient 20-bytes ID which is the concatenation of a <c>base36</c> encoded
/// machine name and <c>base32</c> encoded <see cref="long"/> using the alphabet <c>0-9</c> and <c>A-V</c>.
/// </summary>
public static class IdGenerator
{
// Base32 encoding - in ascii sort order for easy text based sorting
private static readonly char[] s_encode32Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUV".ToCharArray();
private static readonly char[] _prefix = new char[6];
private static void PopulatePrefix()
{
var machineHash = Math.Abs(Environment.MachineName.GetHashCode());
var machineEncoded = Base36.Encode(machineHash);
var i = _prefix.Length - 1;
var j = 0;
while (i >= 0)
{
if (j < machineEncoded.Length)
{
_prefix[i] = machineEncoded[j];
j++;
} else {
_prefix[i] = '0';
}
i--;
}
}
static IdGenerator()
{
PopulatePrefix();
}
private static long _lastId = DateTime.UtcNow.Ticks;
public static string Next() => GenerateId(Interlocked.Increment(ref _lastId));
private static string GenerateId(long id)
{
char[] encode32Chars = s_encode32Chars;
char[] prefixChars = _prefix;
var buffer = new char[20];
buffer[19] = prefixChars[5];
buffer[18] = prefixChars[4];
buffer[17] = prefixChars[3];
buffer[16] = prefixChars[2];
buffer[15] = prefixChars[1];
buffer[14] = prefixChars[0];
buffer[13] = '-';
buffer[12] = encode32Chars[id & 31];
buffer[11] = encode32Chars[(id >> 5) & 31];
buffer[10] = encode32Chars[(id >> 10) & 31];
buffer[9] = encode32Chars[(id >> 15) & 31];
buffer[8] = encode32Chars[(id >> 20) & 31];
buffer[7] = encode32Chars[(id >> 25) & 31];
buffer[6] = encode32Chars[(id >> 30) & 31];
buffer[5] = encode32Chars[(id >> 35) & 31];
buffer[4] = encode32Chars[(id >> 40) & 31];
buffer[3] = encode32Chars[(id >> 45) & 31];
buffer[2] = encode32Chars[(id >> 50) & 31];
buffer[1] = encode32Chars[(id >> 55) & 31];
buffer[0] = encode32Chars[(id >> 60) & 31];
return new string(buffer, 0, buffer.Length);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment