Dot Net Perls

Static Constructor - C#

by Sam Allen

Problem

Are static constructors slow? Microsoft and many developers warn that static constructors in a class impose an unacceptable overhead for all operations with that class. Compare static constructors with lazy initialization and provide benchmarks.

Solution: C#

What I found is that static classes do cause a slowdown of all accesses to the class. However, if you have members that always must be initialized anyways, the static constructor can be faster.

Non-trivial. What I am comparing here are non-trivial initializations. If you have initializations that can be put directly in the class declaration, do that. (Simply type "object _o = new object();" directly in the class.)

Comparison of classes. The first class here uses a static constructor, which is guaranteed to run before any of the static members are used. The static constructor usually runs on first use, lazily. However, every access to the class afterwards must check to see if the constructor has run.

//
// A.
// Class with static constructor.
//
static class ClassA
{
    //
    // 1.
    // Assume we can't allocate directly here
    //
    static object _o;

    //
    // 2.
    // Access with property
    //
    public static object O
    {
        get
        {
            return _o;
        }
    }

    //
    // Include static constructor
    //
    static ClassA()
    {
        _o = new object();
    }

    //
    // 3.
    // Property that doesn't require initialization
    //
    public static object O2
    {
        get
        {
            return new object();
        }
    }
}
  1. Static object declared
    Point 1 above shows the static object we will access. This object must be initialized and the initialization won't be done on the same line.
  2. Property O
    This property relies on the object _o being initialized. In this example, the static constructor does that. The static constructor is guaranteed to run, which is why this works.
  3. Property O2
    This is just an example property that doesn't require anything to be initialized in the static constructor. You will see that this property is slowed down a lot because of the static constructor, which it doesn't need.

Version without static constructor

The above class can be expressed without a static constructor at all. This has both a positive and negative performance impact. You will see that the property that requires an initialization is slowed down a bit, but the property that doesn't is sped up a lot.

//
// B.
// Regular static class.
//
static class ClassB
{
    //
    // 1.
    // Assume we can't allocate directly here
    //
    static object _o;

    //
    // 2.
    // Access with property but check for null
    //
    public static object O
    {
        get
        {
            if (_o == null)
            {
                _o = new object();
            }
            return _o;
        }
    }

    //
    // 3.
    // Property that doesn't require initialization
    //
    public static object O2
    {
        get
        {
            return new object();
        }
    }
}
  1. Static object
    The object is the same in this class as it was in the previous class shown.
  2. Property O
    Because this class has no static constructor, we must do the initialization in the property here. (Assume we can't do it directly in the declaration.)
  3. Property O2
    This property doesn't require any initialization done, so it is must faster when there isn't a static constructor.

So what happens?

What happens is that the static constructor imposes a performance penalty on all accesses to its class. When there isn't a static constructor, the performance penalty only occurs when a specific property is accessed and it must be checked.

What's the difference? Eliminating the static constructor allows you to isolate the performance penalty to where it is needed. This will usually speed up more parts of the program than it slows down.

So what's best? My rule of thumb is to avoid static constructors always. They cause slowdowns in code that doesn't need to be slowed down, and using the lazy-initialization pattern as shown in the second code pattern property O is more logical and easier to optimize.

How much impact? The impact of static constructors is non-trivial. I benchmarked 1 billion operations on the above classes. The first graph shows performance when the static constructor is useful.

Details. Times in the above graphs are 3790 ms and 5070 ms in the first graph, and 7878 ms and 5663 ms in the second. Compilation mode was Release and .NET 3.5 was used.

What does it mean?

It means that static constructors slow everything down, but when they are needed, they are faster than alternatives. Use static constructors only when every part of your class requires initialization in the static constructor.

Conclusion

Static constructors should be used rarely and only in classes where every property and member relies on the static constructor. Usually they provide little benefit, and more often than not they are a negative. As a result of this experiment, I avoid static classes.

Dot Net Perls
About
Sitemap
Source code
RSS
Language Features
Struct Examples and Tricks
Run Commands With Process.Start
Singleton Pattern vs. Static Class
NGEN Installer Class
Enum Tips and Examples
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.