Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>When requesting <code>Queue.Synchonized</code> you get a <code>SynchronizedQueue</code> in return which uses a <code>lock</code> very minimally around calls to <code>Enqueue</code> and <code>Dequeue</code> on an inner queue. Therefore, the performance should be the same as using a <code>Queue</code> and managing locking yourself for <code>Enqueue</code> and <code>Dequeue</code> with your own <code>lock</code>. </p> <p>You are indeed imagining things - they should be the same.</p> <p><strong>Update</strong></p> <p>There is actually the fact that when using a <code>SynchronizedQueue</code> you are adding a layer of indirection as you have to go through the wrapper methods to get to the inner queue which it is managing. If anything this should slow things down very fractionally as you've got an extra frame on the stack that needs to be managed for each call. God knows if in-lining cancels this out though. Whatever - it's <em>minimal</em>.</p> <p><strong>Update 2</strong></p> <p>I have now benchmarked this, and as predicted in my previous update:</p> <blockquote> <p>"Queue.Synchronized" is slower than "Queue+lock"</p> </blockquote> <p>I carried out a single-threaded test as they both use the same locking technique (i.e. <code>lock</code>) so testing pure overhead in a "straight line" seems reasonable.</p> <p>My benchmark produced the following results for a <strong>Release</strong> build:</p> <pre><code>Iterations :10,000,000 Queue+Lock :539.14ms Queue+Lock :540.55ms Queue+Lock :539.46ms Queue+Lock :540.46ms Queue+Lock :539.75ms SynchonizedQueue:578.67ms SynchonizedQueue:585.04ms SynchonizedQueue:580.22ms SynchonizedQueue:578.35ms SynchonizedQueue:578.57ms </code></pre> <p>Using the following code:</p> <pre><code>private readonly object _syncObj = new object(); [Test] public object measure_queue_locking_performance() { const int TestIterations = 5; const int Iterations = (10 * 1000 * 1000); Action&lt;string, Action&gt; time = (name, test) =&gt; { for (int i = 0; i &lt; TestIterations; i++) { TimeSpan elapsed = TimeTest(test, Iterations); Console.WriteLine("{0}:{1:F2}ms", name, elapsed.TotalMilliseconds); } }; object itemOut, itemIn = new object(); Queue queue = new Queue(); Queue syncQueue = Queue.Synchronized(queue); Action test1 = () =&gt; { lock (_syncObj) queue.Enqueue(itemIn); lock (_syncObj) itemOut = queue.Dequeue(); }; Action test2 = () =&gt; { syncQueue.Enqueue(itemIn); itemOut = syncQueue.Dequeue(); }; Console.WriteLine("Iterations:{0:0,0}\r\n", Iterations); time("Queue+Lock", test1); time("SynchonizedQueue", test2); return itemOut; } [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")] private static TimeSpan TimeTest(Action action, int iterations) { Action gc = () =&gt; { GC.Collect(); GC.WaitForFullGCComplete(); }; Action empty = () =&gt; { }; Stopwatch stopwatch1 = Stopwatch.StartNew(); for (int j = 0; j &lt; iterations; j++) { empty(); } TimeSpan loopElapsed = stopwatch1.Elapsed; gc(); action(); //JIT action(); //Optimize Stopwatch stopwatch2 = Stopwatch.StartNew(); for (int j = 0; j &lt; iterations; j++) action(); gc(); TimeSpan testElapsed = stopwatch2.Elapsed; return (testElapsed - loopElapsed); } </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