Andy's observations as he continues to attempt to know all that is .NET...

Wednesday, September 17, 2008

.NET 3.5 SP1 produces a re think of Optimised Lazy Singleton

In the past I've used a version of double check locking in order to implement efficient lazy creation of a singleton in .NET.  This I've found to be the most performant implementation.  However I've noticed recently that things are changing, when I run the code on a 64 bit CLR I see no difference between a type that has the  before field init attribute present on or not.  Both get initialised lazily in release mode and extremely quickly.  The double check locking on 64 bit CLR is found to be less performant and therefore an unnecessary complication in the implementation.

In addition Ive recently installed .NET 3.5 SP1 and noticed now that there is a change in the 32 bit CLR for type initialisation.  Whilst I still get the normal behaviour of before field init, the lazy CLR based initialisation is now extremely quick, almost the same as non lazy initialisation of the type.  Again more importantly faster than my optimised double check locking implementation

My conclusion therefore is that moving forward, I'm comfortable in the fact that the very simple of singleton implementations is now acceptable even in cases where I'm aggressively requesting an instance of the singleton.

Below are two implementations of a singleton, the first using optimised locking the second using the CLR type initialisation to ensure lazy initialisation even in a multi threaded environment.

public class OptimisedLazyLogger
    {
        private static volatile OptimisedLazyLogger instance;
        private static object creationLock = new object();

        private OptimisedLazyLogger()
        {
        }

        public static OptimisedLazyLogger GetInstance()
        {
            if (instance == null)
            {
                CreateInstance();
            }

            return instance;
        }

        private static void CreateInstance()
        {
            // only one thread at any one time
            // can be inside this block
            lock (creationLock)
            {
                if (instance == null)
                {
                    instance = new OptimisedLazyLogger();
                }
            }
        }

         }

Implementation relying on CLR lazy initialisation

class LazyLogger
    {
        private static LazyLogger instance;

        // Type constructor
        static LazyLogger()
        {
            instance = new LazyLogger();
        }

        // ensure new can not be used outside the type
        // to create an instance
         private LazyLogger()
        {
            Console.WriteLine("Lazy Logger Created");
        }

        // Public method to allow clients to get to the single
        // instance
         public static LazyLogger GetInstance()
        {
            return instance;
        }

        public void LogMsg(string msg)
        {
            Console.WriteLine("Logger: {0}" , msg );
        }

}

No comments:

About Me

My photo
Im a freelance consultant for .NET based technology. My last real job, was at Cisco System were I was a lead architect for Cisco's identity solutions. I arrived at Cisco via aquisition and prior to that worked in small startups. The startup culture is what appeals to me, and thats why I finally left Cisco after seven years.....I now filll my time through a combination of consultancy and teaching for Developmentor...and working on insane startups that nobody with an ounce of sense would look twice at...