Performance tips

2010/05/04

Performance tips

Reactive Queue, IObservable, Performance, ManualResetEventSlim , WaitHandle

recently I was working on the Reactive Queue (which is part of the Rx Contrib).

the requirement for the Reactive Queue was to to achieve the highest throughput possible

for each queue provider (2,000,000 messages of 500 byte per second using Concurrent Queue provider

running on simple quad server).

while working on this project I was encounter the the following performance hits:

 

1. ManualResetEventSlim

there is a big difference between using the old ManualResetEvent Vs. ManualResetEventSlim the hit

factor can go up to 2 or 3 times slower if you having a very short synchronization period

(the ManualResetEventSlim does not escalate to kernel mode on short period waiting).

 

2. ManualResetEventSlim.WaitHandle

do not expose the ManualResetEventSlim instance using the WaitHandle, as shown in the following code snippet:

Code Snippet
  1. private readonly ManualResetEventSlim _syncWhileWorkingHandle;
  2. public WaitHandle WaitWhileWorkingHandle
  3. {
  4.     get { return _syncWhileWorkingHandle.WaitHandle; }
  5. }

consuming ManualResetEventSlim though its WaitHandle property does not gain

performance improvements benefits.

if you do want to expose synchronization API, use the following code:

Code Snippet
  1. private readonly ManualResetEventSlim _syncWhileWorkingHandle;
  2. public void WaitWhileWorking()
  3. {
  4.     _syncWhileWorkingHandle.Wait();
  5. }

 

3. CancellationToken

when ever using CancellationToken:

Code Snippet
  1. var cancel = new CancellationTokenSource();
  2. Task.Factory.StartNew(Dequeuing, cancel.Token);

do monitor GC collect counter, especially the 3rd generation collection.

trying to use this technique I got a huge hit (3.5 times slower), because of

extra (multiple) GC 3rd generation collection.

instead of using the CancellationToken the Reactive Queue is using old good

dispose pattern.

 

4. Thread.Yield()

do consider to use Thread.Yield().

putting it on the right places may improve overall performance,

but you have to be careful and measure the actual performance, because

doing it on the wrong places may result as performance hit.

 

Summary

performance improving required continuously measurement which should

be compared with historical measurement.

be careful with synchronization and do use the new .net synchronization types like ManualResetEventSlim.

 

kick it on DotNetKicks.com Shout it


Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>