Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Empirically, the overhead appears to be, in the best case, ~270% on 32 bit JIT and ~200% on 64 bit (and the overhead gets worse the more times you "call" <code>fixed</code>). So I'd try to minimise your <code>fixed</code> blocks if performance is really critical. </p> <p>Sorry, I'm not familiar enough with fixed / unsafe code to know why that's the case</p> <hr> <p><strong>Details</strong></p> <p>I also added some <code>TestMore</code> methods which call your two test methods 10 times instead of 2 to give a more real world scenario of multiple methods being called on your <code>fixed</code> struct.</p> <p>The code I used:</p> <pre><code>class Program { static void Main(string[] args) { var someData = new ByteArray(); int iterations = 1000000000; var multiple = new MultipleFixed(); var single = new SingleFixed(); // Warmup. for (int i = 0; i &lt; 100; i++) { multiple.Test(ref someData); single.Test(ref someData); multiple.TestMore(ref someData); single.TestMore(ref someData); } // Environment. if (Debugger.IsAttached) Console.WriteLine("Debugger is attached!!!!!!!!!! This run is invalid!"); Console.WriteLine("CLR Version: " + Environment.Version); Console.WriteLine("Pointer size: {0} bytes", IntPtr.Size); Console.WriteLine("Iterations: " + iterations); Console.Write("Starting run for Single... "); var sw = Stopwatch.StartNew(); for (int i = 0; i &lt; iterations; i++) { single.Test(ref someData); } sw.Stop(); Console.WriteLine("Completed in {0:N3}ms - {1:N2}/sec", sw.Elapsed.TotalMilliseconds, iterations / sw.Elapsed.TotalSeconds); Console.Write("Starting run for More Single... "); sw = Stopwatch.StartNew(); for (int i = 0; i &lt; iterations; i++) { single.Test(ref someData); } sw.Stop(); Console.WriteLine("Completed in {0:N3}ms - {1:N2}/sec", sw.Elapsed.TotalMilliseconds, iterations / sw.Elapsed.TotalSeconds); Console.Write("Starting run for Multiple... "); sw = Stopwatch.StartNew(); for (int i = 0; i &lt; iterations; i++) { multiple.Test(ref someData); } sw.Stop(); Console.WriteLine("Completed in {0:N3}ms - {1:N2}/sec", sw.Elapsed.TotalMilliseconds, iterations / sw.Elapsed.TotalSeconds); Console.Write("Starting run for More Multiple... "); sw = Stopwatch.StartNew(); for (int i = 0; i &lt; iterations; i++) { multiple.TestMore(ref someData); } sw.Stop(); Console.WriteLine("Completed in {0:N3}ms - {1:N2}/sec", sw.Elapsed.TotalMilliseconds, iterations / sw.Elapsed.TotalSeconds); Console.ReadLine(); } } unsafe struct ByteArray { public fixed byte Data[1024]; } class MultipleFixed { unsafe void SetValue(ref ByteArray bytes, int index, byte value) { fixed (byte* data = bytes.Data) { data[index] = value; } } unsafe bool Validate(ref ByteArray bytes, int index, byte expectedValue) { fixed (byte* data = bytes.Data) { return data[index] == expectedValue; } } public void Test(ref ByteArray bytes) { SetValue(ref bytes, 0, 1); Validate(ref bytes, 0, 1); } public void TestMore(ref ByteArray bytes) { SetValue(ref bytes, 0, 1); Validate(ref bytes, 0, 1); SetValue(ref bytes, 0, 2); Validate(ref bytes, 0, 2); SetValue(ref bytes, 0, 3); Validate(ref bytes, 0, 3); SetValue(ref bytes, 0, 4); Validate(ref bytes, 0, 4); SetValue(ref bytes, 0, 5); Validate(ref bytes, 0, 5); } } class SingleFixed { unsafe void SetValue(byte* data, int index, byte value) { data[index] = value; } unsafe bool Validate(byte* data, int index, byte expectedValue) { return data[index] == expectedValue; } public unsafe void Test(ref ByteArray bytes) { fixed (byte* data = bytes.Data) { SetValue(data, 0, 1); Validate(data, 0, 1); } } public unsafe void TestMore(ref ByteArray bytes) { fixed (byte* data = bytes.Data) { SetValue(data, 0, 1); Validate(data, 0, 1); SetValue(data, 0, 2); Validate(data, 0, 2); SetValue(data, 0, 3); Validate(data, 0, 3); SetValue(data, 0, 4); Validate(data, 0, 4); SetValue(data, 0, 5); Validate(data, 0, 5); } } } </code></pre> <p>And the results in .NET 4.0, 32 bit JIT:</p> <pre><code>CLR Version: 4.0.30319.239 Pointer size: 4 bytes Iterations: 1000000000 Starting run for Single... Completed in 2,092.350ms - 477,931,580.94/sec Starting run for More Single... Completed in 2,236.767ms - 447,073,934.63/sec Starting run for Multiple... Completed in 5,775.922ms - 173,132,528.92/sec Starting run for More Multiple... Completed in 26,637.862ms - 37,540,550.36/sec </code></pre> <p>And in .NET 4.0, 64 bit JIT:</p> <pre><code>CLR Version: 4.0.30319.239 Pointer size: 8 bytes Iterations: 1000000000 Starting run for Single... Completed in 2,907.946ms - 343,885,316.72/sec Starting run for More Single... Completed in 2,904.903ms - 344,245,585.63/sec Starting run for Multiple... Completed in 5,754.893ms - 173,765,185.93/sec Starting run for More Multiple... Completed in 18,679.593ms - 53,534,358.13/sec </code></pre>
    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.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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