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.
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();
}
}
}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();
}
}
}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.
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.
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.