ipjohnson / Grace

Grace is a feature rich dependency injection container library
MIT License
337 stars 33 forks source link

Move away from Guid.NewGuid().ToString() for unique string id #72

Closed ipjohnson closed 7 years ago

ipjohnson commented 7 years ago

While Guid.NewGuid does generate a completely unique id, it's 36 characters long. This makes hashing and equality comparisons take longer.

The reality is we only need uniqueness within the process space and make a good faith effort to avoid collisions with user saved extra data.

With that in mind I'm going to introduce the following class that will generate unique id's that are 4characters + N (number always incrementing)

public static class UniqueStringId
{
        private static ThreadLocal<Random> _local = new ThreadLocal<Random>(() => new Random());
        private static int _counter;

        public static string Generate()
        {
            var intValue = _local.Value.Next();

            StringBuilder builder = new StringBuilder();

            builder.Append((char)(intValue % 95 + 32));
            intValue = intValue >> 7;
            builder.Append((char)(intValue % 95 + 32));
            intValue = intValue >> 7;
            builder.Append((char)(intValue % 95 + 32));
            intValue = intValue >> 7;
            builder.Append((char)(intValue % 95 + 32));
            builder.Append(Interlocked.Increment(ref _counter));

            return builder.ToString();
        }
}
ipjohnson commented 7 years ago

This is complete. The final implementation looks like this

    public static class UniqueStringId
    {
        private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() => new Random());
        private static int _counter;

        /// <summary>
        /// Generate string that is unique to this process
        /// </summary>
        /// <returns></returns>
        public static string Generate()
        {
            var intValue = _local.Value.Next();

            return new string(new[]
            {
                (char)(intValue % 95 + 32),
                (char)((intValue >> 7) % 95 + 32),
                (char)((intValue >> 14) % 95 + 32),
                (char)((intValue >> 21) % 95 + 32)
            }) 
            + Interlocked.Increment(ref _counter);
        }
    }