OutOfMemoryException running published Rx performance test

Unanswered OutOfMemoryException running published Rx performance test

  • Friday, November 09, 2012 4:05 PM
     
      Has Code

    Hi,

    I'm following along in Bart's article from March this year on Rx 2.0 enhancements.

    http://blogs.msdn.com/b/rxteam/archive/2012/03/12/reactive-extensions-v2-0-beta-available-now.aspx

    I tried running one of the performance tests using Rx 2.0 RTM and .NET Framework 4.0, and encountered an OutOfMemoryException. Specifically, I tried this test:

    static void Survival<TFittest>()
    {
        var xs = new Fast().Delay(TimeSpan.FromSeconds(5));
    
        var c = new Count<int>();
    
        var sw = Stopwatch.StartNew();
        using (xs.Subscribe(c))
            Thread.Sleep(30000);
        sw.Stop();
    
        Console.WriteLine(c.Total / sw.Elapsed.TotalSeconds + " msgs/s");
    }

    This is supposed to be a test of memory allocation related to the Delay operator. When I run this program, I get an OutOfMemoryException within a couple seconds.

    Anyone have an idea why this might be happening? My machine is running at 5.46GB right now. I have 8GB of RAM. When I start the process, memory grows to 6.22GB and then the process dies.

    Interesting if I change the delay to 1 ms, I still get an OutOfMemoryException.

    Any ideas why this is happening?

    Thanks,
    Ranjith

All Replies

  • Friday, November 09, 2012 5:36 PM
     
      Has Code

    Hi Ranjith,

    I can't reproduce the problem with .NET 4.5.  I didn't try with .NET 4.0 though.  Maybe you could try against .NET 4.5?

    I just tested against Rx 2.0.21103.1 (assembly version 2.0.20823.0) for .NET 4.5.  After running the test 3 times in a row, to warm up caches, here were the final results:

    110527.702672517 msgs/s

    Memory <= 600 MB
    ~2 garbage collections

    My computer: 

    Windows 8 Pro, x64
    Intel(R) Xeon(TM) CPU 3.40GHz, 3391 Mhz, 1 Core(s), 2 Logical Processor(s)
    Installed Physical Memory (RAM) 4.00 GB
    Available Physical Memory 1.91 GB

    Here is the complete code, taken from the Rx Team's blog post:

    Note: I've changed it slightly to run inside of a lab application, so technically the code was hosted in a WPF UserControl instead of a console window during my tests, though I suspect that if I were to run a pure console app the results would be the same.

    using System;
    using System.Diagnostics;
    using System.Reactive.Disposables;
    using System.Reactive.Linq;
    using System.Threading;
    
    namespace Rxx.Labs.Performance
    {
    	public sealed class DelayThroughputLab : BaseConsoleLab
    	{
    		protected override void Main()
    		{
    			var xs = new Fast().Delay(TimeSpan.FromSeconds(5));
    
    			var c = new Count<int>();
    
    			var sw = Stopwatch.StartNew();
    			using (xs.Subscribe(c))
    				Thread.Sleep(30000);
    			sw.Stop();
    
    			TraceLine(c.Total / sw.Elapsed.TotalSeconds + " msgs/s");
    		}
    
    		class Count<T> : IObserver<T>
    		{
    			public int Total;
    
    			public void OnNext(T value)
    			{
    				Total++;
    			}
    
    			public void OnError(Exception error)
    			{
    				throw new NotImplementedException();
    			}
    
    			public void OnCompleted()
    			{
    				throw new NotImplementedException();
    			}
    		}
    
    		class Fast : IObservable<int>
    		{
    			public IDisposable Subscribe(IObserver<int> observer)
    			{
    				var d = new BooleanDisposable();
    
    				new Thread(() =>
    				{
    					while (!d.IsDisposed)
    						observer.OnNext(42);
    				}).Start();
    
    				return d;
    			}
    		}
    	}
    }
    - Dave

    http://davesexton.com/blog

  • Friday, November 09, 2012 5:54 PM
     
     

    Hi Ranjith,

    I just tested in a console app targeting .NET 4.0 and I still couldn't reproduce your error.  The results were similar to my previous test targeting .NET 4.5.

    - Dave


    http://davesexton.com/blog

  • Friday, November 09, 2012 7:47 PM
     
     

    Hmmm. Thanks for testing, Dave. I'm not sure what I'm doing wrong. I created a console app targeting .NET Framework 4, and I'm running it on Windows 7 Enterprise.  I tried compiling the app as 64 bit, but that didn't help.

    Here's my exact code:

    namespace Performance
    {
    class Program
    {
    static void Main(string[] args)
    {
    var xs = new Fast().Delay(TimeSpan.FromSeconds(5));

    var c = new Count<int>();

    var sw = Stopwatch.StartNew();
    using (xs.Subscribe(c))
    Thread.Sleep(30000);
    sw.Stop();

    Console.WriteLine(c.Total / sw.Elapsed.TotalSeconds + " msgs/s");
    }

    class Count<T> : IObserver<T>
    {
    public int Total;

    public void OnNext(T value)
    {
    Total++;
    }

    public void OnError(Exception error)
    {
    throw new NotImplementedException();
    }

    public void OnCompleted()
    {
    throw new NotImplementedException();
    }
    }

    class Fast : IObservable<int>
    {
    public IDisposable Subscribe(IObserver<int> observer)
    {
    var d = new BooleanDisposable();

    new Thread(() =>
    {
    while (!d.IsDisposed)
    observer.OnNext(42);
    }).Start();

    return d;
    }
    }
    }
    }

  • Saturday, November 10, 2012 11:04 AM
     
     

    Hi Ranjith,

    Have you tried running a profiler such as Visual Studio, PerfView or CLRProfiler?  Perhaps it would be useful to see the actual allocations and the hot execution path.

    - Dave


    http://davesexton.com/blog

  • Saturday, November 10, 2012 11:05 AM
     
     

    Hi Ranjith,

    Just to be clear, have you updated to the latest version of Rx 2.0?  You can download it from NuGet.  This is the version that I used when testing.

    - Dave


    http://davesexton.com/blog