Static constructors cause a performance overhead?
I think "substantial" is an overstatement in most use cases.
Having a static constructor (even if it does nothing) affects type initialization time due to the presence/absence of the beforefieldinit flag. There are stricter guarantees about timing when you have a static constructor.
For most code, I'd suggest this doesn't make much difference - but if you're tight-looping and accessing a static member of a class, it might. Personally I wouldn't worry about it too much - if you have a suspicion that it's relevant in your real application, then test it rather than guessing. Microbenchmarks are very likely to exaggerate the effect here.
It's worth noting that .NET 4 behaves somewhat differently to previous versions when it comes to type initialization - so any benchmarks should really show the different versions in order to be relevant.
The CLR provides a pretty strong guarantee for the execution of static constructors, it promises to call them only once and before any method in the class can run. That guarantee is fairly tricky to implement when there are multiple threads using the class.
Taking a peek at the CLR source code for SSCLI20, I see a fairly large chunk of code dedicated to providing this guarantee. It maintains a list of running static constructors, protected by a global lock. Once it gets an entry in that list, it switches to a class specific lock which ensures no two threads can be running the constructor. Double-checked locking on a status bit that indicates that the constructor was already run. Lots of inscrutable code that provides exception guarantees.
Well, this code doesn't come for free. Add it to the execution time for the cctor itself and you're looking at some overhead. As always, don't let this cramp your style, this guarantee is also a very nice one that you wouldn't want to provide yourself. And measure before you fix.
Well I've just replicated his test.
For 1000000000 iterations with a DEBUG build I get:
- 4s for his static class with a static constructor
- 3.6s same class with commented out static constructor
- 2.9s with the class non-static (and creating an instance before the iteration) with either a static constructor or not
The same with a RELEASE build does highlight a difference:
- Static class with static constructor: 4046.875ms
- Static class with no static constructor: 484.375ms
- Instance with static constructor: 484.375ms
- Instance with no static constructor: 484.375ms