Note that there are some explanatory texts on larger screens.

plurals
  1. POInterlocked.Read / Interlocked.Exchange much slower on Mono than .NET?
    primarykey
    data
    text
    <p><strong>Sorry for the long question, but there's a Jon Skeet reference, so it may be worthwhile for some.</strong></p> <p><strong>In short:</strong><br /> <code>Interlocked.Read</code> / <code>Interlocked.Exchange</code> seem to perform much slower while running in the Mono framework than while running in the .NET framework. I'm curious to know why.</p> <p><strong>In long:</strong><br /> I wanted a thread-safe double for 32-bit platforms, so I made this struct:</p> <pre><code>public interface IThreadSafeDouble { double Value { get; set; } } public struct LockedThreadSafeDouble : IThreadSafeDouble { private readonly object Locker; private double _Value; public double Value { get { lock (Locker) return _Value; } set { lock (Locker) _Value = value; } } public LockedThreadSafeDouble(object init) : this() { Locker = new object(); } } </code></pre> <p>Then I read Jon Skeet's answer to <a href="https://stackoverflow.com/questions/531759/c-sharp-volatile-double">this question</a>, so I made this struct:</p> <pre><code>public struct InterlockedThreadSafeDouble : IThreadSafeDouble { private long _Value; public double Value { get { return BitConverter.Int64BitsToDouble(Interlocked.Read(ref _Value)); } set { Interlocked.Exchange(ref _Value, BitConverter.DoubleToInt64Bits(value)); } } } </code></pre> <p>Then I wrote this test:</p> <pre><code> private static TimeSpan ThreadSafeDoubleTest2(IThreadSafeDouble dbl) { var incrementTarg = 10000000; var sw = new Stopwatch(); sw.Start(); for (var i = 0; i &lt; incrementTarg; i++, dbl.Value++); sw.Stop(); return sw.Elapsed; } private static void ThreadSafeTest() { var interlockedDbl = new InterlockedThreadSafeDouble(); var interlockedTim = ThreadSafeDoubleTest2(interlockedDbl); var lockedDbl = new LockedThreadSafeDouble(true); var lockedTim = ThreadSafeDoubleTest2(lockedDbl); System.Console.WriteLine("Interlocked Time: " + interlockedTim); System.Console.WriteLine("Locked Time: " + lockedTim); } public static void Main(string[] args) { for (var i = 0; i &lt; 5; i++) { System.Console.WriteLine("Test #" + (i + 1)); ThreadSafeTest(); } System.Console.WriteLine("Done testing."); System.Console.ReadLine(); } </code></pre> <p>And I got this result using the .NET framework: <img src="https://i.stack.imgur.com/QFvz9.jpg" alt=".NET Interlocked test results"></p> <p>And this result using the Mono framework: <img src="https://i.stack.imgur.com/Qme8Q.jpg" alt="Mono Interlocked test results"></p> <p>I've ran both tests multiple times on the same machine (Windows XP) and the results are consistent. I'm curious to know why Interlocked.Read/Interlocked.Exchange seems to perform so much slower on the Mono framework.</p> <p><strong>Update:</strong></p> <p>I wrote the following, simpler test:</p> <pre><code>long val = 1; var sw = new Stopwatch(); sw.Start(); for (var i = 0; i &lt; 100000000; i++) { Interlocked.Exchange(ref val, 2); // Interlocked.Read(ref val); } sw.Stop(); System.Console.WriteLine("Time: " + sw.Elapsed); </code></pre> <p>The .NET framework consistently returns <strong>~2.5</strong> seconds with both <code>Exchange</code> and <code>Read</code>. The Mono framework returns <strong>~5.1</strong> 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.
 

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