Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

Playing with Roslyn

time to read 3 min | 554 words

We do a lot of compiler work in RavenDB. Indexes are one such core example, where we take the C# language and beat both it and our heads against the wall until it agrees to do what we want it to.

A lot of that is happening using the excellent NRefactory library as well as the not so excellent CodeDOM API. Basically, we take a source string, convert it into something that can run, then compile it on the fly and execute it.

I decided to check the implications of using this using a very trivial benchmark:

private static void CompileCodeDome(int i)
    var src = @"
class Greeter
static void Greet()
System.Console.WriteLine(""Hello, World"" + " + i + @");
    CodeDomProvider codeDomProvider = new CSharpCodeProvider();
    var compilerParameters = new CompilerParameters
        OutputAssembly= "Greeter.dll",
        GenerateExecutable = false,
        GenerateInMemory = true,
        IncludeDebugInformation = false,
        ReferencedAssemblies =
            typeof (object).Assembly.Location,
            typeof (Enumerable).Assembly.Location
    CompilerResults compileAssemblyFromSource = codeDomProvider.CompileAssemblyFromSource(compilerParameters, src);
    Assembly compiledAssembly = compileAssemblyFromSource.CompiledAssembly;

private static void CompileRoslyn(int i)
    var syntaxTree = CSharpSyntaxTree.ParseText(@"
class Greeter
static void Greet()
System.Console.WriteLine(""Hello, World"" + " +i +@");

    var compilation = CSharpCompilation.Create("Greeter.dll",
        syntaxTrees: new[] {syntaxTree},
        references: new MetadataReference[]
            new MetadataFileReference(typeof (object).Assembly.Location),
            new MetadataFileReference(typeof (Enumerable).Assembly.Location),

    Assembly assembly;
    using (var file = new MemoryStream())
        var result = compilation.Emit(file);


I run it several times, and I got (run # on the X axis, milliseconds on the Y axis):


The very first Roslyn invocation is very costly. The next are pretty much nothing. Granted, this is a trivial example, but the CodeDOM (which invokes csc) is both much more consistent but much more expensive in general.


Daan Le Duc

Yeah, i've seen David Fowler talk about this issue with new Visual Studio when you build for very first time. Takes lots of time not sure if the roslyn team is going to fix this.


.NET startup performance caused the Vista rewrite. Vista was supposed to be based on .NET. Then, they removed the CLR from the startup path entirely.

Kirill Osenkov

Roslyn is JITting. You can try ngen install Microsoft.CodeAnalysis.CSharp.dll from admin command prompt to see if this improves the cold Roslyn time.

If you do this in production, preheat Roslyn on a background thread before first use by compiling this exact program in memory.

Ayende Rahien

Kirill, Sure, the problem is that I'm going to be using that in order to reduce startup time :-)


So how about starting with the CodeDOM version, compile via Roslyn on a separate thread. When that compilation has completed, switch out the CodeDOM version for the Roslyn version?

That way you get the best of both worlds!

Ayende Rahien

James, The cost of the CodeDOM isn't high enough to actually justify something like that. This is very costly process.

Pop Catalin

The startup time of Roslyn is due to being a preview and not installed in the GAC. Roslyn preview uses a separate process as compilation server that is loaded at first use and the Rolsyn bytecode is jit-ed on load.


Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats