RavenTestBase - Proper way to use to avoid memory leaks when testing

44 views
Skip to first unread message

Kamran Ayub

unread,
Apr 27, 2016, 9:21:29 AM4/27/16
to RavenDB - 2nd generation document database
I noticed that RavenTestBase in the Helpers project can lead to unexpected memory leaks if used in certain ways--namely, calling NewDocumentStore() even when disposing of them too many times. I imagine this is because the ConcurrentDictionary is holding references to all the stores created in the context of the class and only when the dictionary is disposed/out of scope, then the stores will be cleaned up properly.

For example, this class has two methods, one will leak up to 2GB of memory and one will be fine:

    public class TestClass : RavenTestBase
    {
        [Test]
        public void SomeTest_NoLeak()
        {
            for (var i = 0; i < 500; i++)
            {
                using (var store = new EmbeddableDocumentStore())
                {
                    store.Initialize();
                    Debug.WriteLine(i);
                }
            }
        }

        [Test]
        public void SomeTest_Leak()
        {
            for (var i = 0; i < 1000; i++)
            {
                using (var store = NewDocumentStore())
                {
                    Debug.WriteLine(i);
                }
            }
        }
    }

I imagine that "SomeTest_Leak" is not using the test base in a way that it was meant to--but it was still surprising to see that the stores were not being deallocated, even after disposal.

Is this expected? Even if you call NewDocumentStore() in Setup and dispose it in Teardown, depending on how many tests your test class has, you could be eating up more memory than you expect using this helper library because it'll only be disposed once the class is disposed.

Chris Marisic

unread,
Apr 27, 2016, 10:20:26 AM4/27/16
to RavenDB - 2nd generation document database
I think this might be more of an issue of your test harness than an actual issue.

The GC is not going to invoke in the middle of your method. (And the dispose method on the store should not be invoking GC collect) So the GC is waiting for your method to run to completion.

To the root of your app.config in your test project add:

<gcServerenabled="true" />

https://msdn.microsoft.com/en-us/library/ms229357%28v=vs.110%29.aspx

This will cause the GC to run in the background and you should see it freeing memory during your test. You still might not even see it occur because you're running code in such a tight loop. Add a sleep after every dispose or every 10, 100 disposes.

A separate aspect is to change your code to look like:

[Test]
public void SomeTest_Leak() {
    for (var i = 0; i < 1000; i++) {
        NewStore();
    }
}

public void NewStore() {

    using (var store = NewDocumentStore())
{
        var local = store.DO SOMETHING ()
        Debug.WriteLine(local);
    }
}

Setting your code up like this should allow the GC to better understand the situation you're trying to simulate

Kamran Ayub

unread,
Apr 27, 2016, 1:15:32 PM4/27/16
to RavenDB - 2nd generation document database

Thanks Chris, that's what I thought. I ran into a separate issue due to Ninjects caching that was causing my specific memory leak but ran across this while trying to reproduce.


--
You received this message because you are subscribed to a topic in the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ravendb/s9X8QpysrUw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ravendb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oren Eini (Ayende Rahien)

unread,
Apr 27, 2016, 9:12:24 PM4/27/16
to ravendb
The actual problem is that we assume that you are going to dispose the test class instance when you are done with the test.
This is when we do cleanup.

Hibernating Rhinos Ltd  

Oren Eini l CEO Mobile: + 972-52-548-6969

Office: +972-4-622-7811 l Fax: +972-153-4-622-7811

 


--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.

Kamran Ayub

unread,
Apr 27, 2016, 9:54:27 PM4/27/16
to ravendb

Good to know, thanks!

Reply all
Reply to author
Forward
0 new messages