Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static constructors cause a performance overhead?

Recently read in a article on dotnetpearls.com here saying that static ctors take a substantial amount of perfomance hit.

Could not fathom why?

like image 759
abhilash Avatar asked May 27 '10 14:05

abhilash


3 Answers

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.

like image 174
Jon Skeet Avatar answered Nov 10 '22 21:11

Jon Skeet


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
like image 27
Paolo Avatar answered Nov 10 '22 23:11

Paolo


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.

like image 7
Hans Passant Avatar answered Nov 10 '22 22:11

Hans Passant