C# Singleton Class

One: 1

Singletons make having single instances easy. They allow for single allocations and instances of data. We review the singleton types. We see one of the fastest implementations. And we review other possibilities.

Example

Framework: NET

The singleton design pattern is an interface. It is a popular class type for programs. It allows a class to enforce that it is only allocated once. This is one of the best implementations of singleton.

Interface
Based on:

.NET 4.5

Program that uses singleton: C#

class Program
{
    static void Main()
    {
	SiteStructure s = SiteStructure.Instance;
    }
}

public sealed class SiteStructure
{
    static readonly SiteStructure _instance = new SiteStructure();
    public static SiteStructure Instance
    {
	get
	{
	    return _instance;
	}
    }
    SiteStructure()
    {
	// Initialize.
    }
}
Static

Look at where the new SiteStructure() is initialized. The readonly and static keywords are critical here. Readonly allows thread-safety, and that means it can be only allocated once. It has a public static getter.

And:The public Instance property is used by callers to get the singleton instance.

ReadonlyProperty

Sealed allows the compiler to perform special optimizations during JIT compilation. The final methods above are the private instance constructor and an Initialize method. Private constructors mean the class can only allocate itself.

SealedPrivate ConstructorFxCop

This implementation is fast because the instance member is created directly in its declaration. FxCop warns when you initialize a static member in a static constructor. Static constructors are slower than most constructors.

Also:They cause problems. They are lazily instantiated. Every access to the class must check that the static constructor has run.

Static ConstructorFxCop

Benchmark

Performance optimization

The version here is ten times faster than the version that does a null check. For the version of singleton I call naive, I add null checks and lazily instantiate the structure. Here's a chart that compares 100 million accesses.

Null check singleton: C#

public sealed class Test
{
    static readonly Test _instance;
    public static readonly Test Instance
    {
	if (_instance == null)
	{
	    _instance = new Test();
	}
	return _instance;
    }
    Test()
    {
    }
}

Optimized singleton: C#

public sealed class Test
{
    static readonly Test _instance = new Test();
    public static readonly Test Instance
    {
	get
	{
	    return _instance;
	}
    }
    Test()
    {
    }
}

Singleton benchmark: 1

Null check singleton: 435 ms
Optimized singleton:   42 ms

Field example

Next, we rewrite the property to be a field. The above code block shows the singleton is using a property to be accessed. In the .NET Framework, properties are often inlined by the Common Language Runtime.

However:My testing shows that by exchanging the property for a public field, the benchmark is sped up.

Singleton implemented with public field: C#

class SingletonB
{
    public static readonly SingletonB _instance = new SingletonB();

    public void Test()
    {
	// Code runs.
    }

    SingletonB()
    {
    }
}
//
// Access with:
// SingletonB._instance.Test();
//
Warning: exclamation mark

Timings. We are looking at tiny amounts of time here. The times for the benchmark of 1 billion iterations was 1.935 seconds versus 1.731 seconds. Using the public field is faster. Using properties slows down singletons.

Result:In one million iterations of the Test function in the above version, the program completed in 1.935 seconds. That is efficient.

Note:The public field is over 10% faster. I recommend skipping the public property as shown first and simply using the field.

Singleton benchmark: 2

Singleton:   Property
Time:        1.935 s

Singleton:   Public field
Time:        1.731 s

Rationale. The singleton here is worth optimizing because even tiny improvements matter. The investigation here also helps us understand how the C# compiler works to generate code. We compare public fields and properties here.

Tip:I recommend reading Jon Skeet's "Implementing the Singleton" article. Singleton version 4 is as fast as any option.

Implementing the Singleton: csharpindepth.com

MSIL

Collection abstraction: squares

What is the performance impact of using a singleton? My research found that when you access a singleton in a C# method, the static singleton Instance field must be loaded onto the evaluation stack.

Therefore:Accessing a singleton always incurs a performance hit when first called in a method.

MSIL code for singleton

L_0000: ldsfld class Perls.Metadata Perls.Metadata::Instance
L_0005: ldarg.0
L_0006: ldloca.s data
L_0008: callvirt instance bool Perls.Metadata::TryGetFile(string, class Perls.FileData&)

MSIL code for static class

L_0000: ldarg.0
L_0001: ldloca.s data
L_0003: call bool Perls.Metadata::TryGetFile(string, class Perls.FileData&)
Note

MSIL with singleton. This MSIL is at the start of a method that uses a singleton. The singleton is called Perls.Metadata.Instance, and it is stored at a static field. The ldsfld call loads the static Instance field onto the stack.

ldsfld Instruction

MSIL with static class method. Here we see the same method call as above, but using a static method and class. The MSIL generated does not use the ldsfld opcode, meaning one fewer variable is pushed onto the evaluation stack.

Also:The callvirt is replaced with a call opcode. This also improves performance.

Squares: abstract

Therefore, using a static class will be faster, even though micro-benchmarks don't show this normally. One fewer variable is pushed onto the stack, and the callvirt is replaced with a call, which is slightly faster.

callvirt Instructioncall Instruction

Finally, MSDN provides an article that shows the cost in nanoseconds for static calls, instance calls, and virtual calls. Static calls are typically faster than other types of calls.

Writing Faster Managed Code: MSDN

Note:Singletons require longer MSIL and more instructions, making them slower and causing more code bloat than statics.

Also:Instead of benchmarks, which are difficult to use here because of the JIT compiler, we saw timings from MSDN and the actual MSIL.

Summary

C# programming language

We looked at an implementation of the singleton design pattern. Singletons are critical to our applications. Since they are so frequently used, making them ten times faster and thread-safe is an important improvement.

Further:We explored ways to change the property to a field. This improves performance according to benchmarks.


C#: Static