Note that there are some explanatory texts on larger screens.

plurals
  1. POStatic constructor performance and why we can't specify beforefieldinit
    primarykey
    data
    text
    <p>I came across a difference in speed using the following two structs:</p> <pre><code>public struct NoStaticCtor { private static int _myValue = 3; public static int GetMyValue() { return _myValue; } } public struct StaticCtor { private static int _myValue; public static int GetMyValue() { return _myValue; } static StaticCtor() { _myValue = 3; } } class Program { static void Main(string[] args) { long numTimes = 5000000000; // yup, 5 billion Stopwatch sw = new Stopwatch(); sw.Start(); for (long i = 0; i &lt; numTimes; i++) { NoStaticCtor.GetMyValue(); } sw.Stop(); Console.WriteLine("No static ctor: {0}", sw.Elapsed); sw.Restart(); for (long i = 0; i &lt; numTimes; i++) { StaticCtor.GetMyValue(); } sw.Stop(); Console.WriteLine("with static ctor: {0}", sw.Elapsed); } } </code></pre> <p>Which produces the results:</p> <pre><code>Release (x86), no debugger attached: No static ctor: 00:00:05.1111786 with static ctor: 00:00:09.9502592 Release (x64), no debugger attached: No static ctor: 00:00:03.2595979 with static ctor: 00:00:14.5922220 </code></pre> <p>The compiler produces a static constructor for the <code>NoStaticCtor</code> that is identical to the one explicitly declared in <code>StaticCtor</code>. I understand that the compiler will only emit <code>beforefieldinit</code> when a static constructor is not explicitly defined.</p> <p>They produce <em>almost</em> identical il code, except for one difference, declaring the struct with <code>beforefieldinit</code>, which is where I feel the difference lies since I know it determines when the type constructor is called, though I can't quite figure out why there's such a difference. It assume it isn't <em>calling</em> the type constructor every iteration, since a type constructor can only be called once.<sup>1</sup></p> <p>So,</p> <p>1) Why the time difference between the struct with <code>beforefieldinit</code> and the one without? (I imagine the JITer is doing something extra in the for loop, however, I have no clue how to view the output of the JITer to see what.</p> <p>2) Why did the compiler designers a) not make all structs <code>beforefieldinit</code> be default and b) not give developers the ability to explicitly specify that behavior? Of course, this <em>is</em> assuming you can't, as I haven't been able to find a way.</p> <hr> <p>Edit:</p> <p><sup>1</sup>. <a href="http://pastebin.com/w1AHfCiF" rel="nofollow">I modified the code</a>, essentially running each loop a second time, expecting a improvement, but it wasn't much:</p> <pre><code>No static ctor: 00:00:03.3342359 with static ctor: 00:00:14.6139917 No static ctor: 00:00:03.2229995 with static ctor: 00:00:12.9524860 Press any key to continue . . . </code></pre> <p>I did this because I though, well, <em>maybe</em>, however unlikely it is, the JITer was actually calling the type constructor every iteration. It seems to me the JITer would know the type constructor has already been called and not emit code to do that when the second loop was compiled.</p> <p>In addition to Motti's answer: <a href="http://pastebin.com/BGJYEBHN" rel="nofollow">This code</a> produces better results, because of difference in JITing, the JITing of <code>DoSecondLoop</code> doesn't emit the static ctor check, because it detected it was done previously in <code>DoFirstLoop</code>, causing each loop to perform at the same speed. (~3 seconds)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload