RavenDB performance in your automated tests

by Damian 27. March 2012 08:26

In our automated testes, we usually have a single place that sets up a configured in-memory Raven database which might look something like this:

public static EmbeddableDocumentStore CreateDocumentStore(Assembly assembly)
{
	var store = new EmbeddableDocumentStore())
	store.UseEmbeddedHttpServer = false;
	store.RunInMemory = true;
	store.Initialize();
	IndexCreation.CreateIndexes(assembly, store);
	return store;
}

Over time, I noticed that our tests were geting slower and slower. Turned out that the IndexCreation process, which uses code generation underneath the hood, is a slow process that adds ~70 milliseconds per index per test. Multiply that by 10s of indexes and 1000s of tests and you've got quite a performance hit both on single test runs and test sessions (CI / NCrunch / Mightymoose / R# Test Session etc).

To improve the perfromance of this I removed "IndexCreation.CreateIndexes(assembly, store);" and made it such that we only put the exact index definitions that a test needs into the document store using a predicate. Thus minimising the document store creation time for an individul test.

But I think we can do better...

When running multiple tests in a session, we are often re-creating the same index over-and-over. Or rather, raven is emiting the same code, compiling and loading the same named type over-and-over. Adding a static Dictionary<string, Type> to the static Compile() method improved the performance of provisioning an embedable document store on second and subsequent test runs (if those tests used the same indexes) by at least a factor of 10. That is, second test (that used 2 indexes) run times went from >200ms to ~20ms. This also reduces the impact of a developer failing to properly restricted which indexes are created in a test.

(Side note: A positive side effect of this optimisation is reduced memory usage that is 'leaked' when dynamically loading assemblies.)

While there are probably going to be issues over my implementation hack of a compiled type cache (thread safety for one), I am going to try to get this improvement, or something similar, officially supported.

Update: Well that was quick. The optimization has been added to RavenDB and will be available in a build soon. Apparently it knocked 5-7 mins of Raven's build time. :)

Comments are closed