Sunday, April 28, 2013

Generating TinyUrl Like Id's

I was looking into generating id's for a personal site that I'm doing for fun. The first thing I did was Google around a bit to see what other people are doing. There were some pretty good ideas out there, most of them taking a url and hashing it to a Base64 representation.

That was fine and dandy, but the methods they were using were long and hideous. I'm a huge fan of short and simple approaches because odds are, it's already been done by Microsoft. Since everyone was talking about hashing I figured I would see what this was about in my search result. How to Hash Passswords

It was still a little too complicated. I knew there had to be something simpler. Then I realized that on the Path object you can generate a temporary file name. It's pretty short. I tried it out and it was exactly what I was looking for! I just had to chop off the portion I wanted, since I wanted to restrict it to 7-8 characters.



It's as simple as this:
Path.GetRandomFileName().Substring(0, 7);

Here's my code to check out collision rate and the speed of it of the id generation and chopping.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Reflection;
using System.Diagnostics;

namespace ScratchConsole
{
    public class Program
    {
        static void Main(string[] args)
        {
            int collissionsDetected = 0;
            List uniqueIds = new List();
            List elapsedTimes = new List();

            // 10,000,000
            for (int i = 0; i < 10000000; i++)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                var id = GenerateUID();
                sw.Stop();
                elapsedTimes.Add(sw.ElapsedTicks);
                var collisionDetected = uniqueIds.Contains(id);

                if (collisionDetected)
                {
                    Console.WriteLine("Collision detected for: (" + id + ")");
                    collissionsDetected++;
                }
            }

            Console.WriteLine("Total collisions: " + collissionsDetected);
            long totaltime = 0;

            foreach (var time in elapsedTimes)
                totaltime += time;

            Console.WriteLine("Times in ticks");
            Console.WriteLine("Longest Time: " + elapsedTimes.OrderByDescending(c => c).First());
            Console.WriteLine("Average Time: " + totaltime / elapsedTimes.Count);
            Console.WriteLine("Fastest Time: " + elapsedTimes.Last());
        }

        public static string GenerateUID()
        {
            return Path.GetRandomFileName().Substring(0, 7);
        }
    }
}
The output looks like this:
10 Million Runs @ 7 Characters

Total collisions: 0
Times in ticks
Longest Time: 6
Average Time: 6
Fastest Time: 5
Press any key to continue . . .

No comments:

Post a Comment