Avoid VBCSCompiler perf hit on Roslyn powered ASP.

2019-03-30 09:30发布

问题:

In order to support C# 6 in our Razor views on MVC5, we turned on the Roslyn compiler platform via web.config:

<system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
    </compilers>
</system.codedom>

However, after production deployments, each view/controller appears to have a noticeable "First Load" delay that is worse than without this compiler being enabled.

Importantly, this delay is in addition to the regular JIT delay you get from a new site being deployed. Pages are noticably slower, while it appears VBCSCompiler.exe runs in the background to "further compile" these pages.

Is there a best practice for pre-compiling/optimizing this situation to eliminate the first-load runtime delay post deployment? Ideally VBCSCompiler.exe is not running after a deployment occurs, and is performed at build-time.

I've seen mentions of aspnet_compiler.exe and have come across StackExchange.Precompilation (see https://blog.stackoverflow.com/2015/07/announcing-stackexchange-precompilation/) and wonder if this is the right fix.

Does anyone have any experience with this particular problem? Thank you.

回答1:

You can use the RoslynRazorViewEngine from StackExchange.Precompilation:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RoslynRazorViewEngine());

The main goal of this view engine, however, is not to get rid of the startup perf hit. With it you just get C#6 support. The views still have to be compiled on first load, but the roslyn assemblies end up in the app domain afterwards, and you get a higher memory footprint. Since roslyn is called in the app, you don't need special permissions on the web server for executing another .exe from the /bin folder. We mostly use this for development on our dev machines.

I strongly recommend you just precompile all the views. This way you get no startup perf hit, and you gain compile time verification of your views. You could even run analyzers on the generated view code. That's what StackOverflow currently runs in production.

I mention aspnet_compiler.exe in that blog post, because it's the original tool for precompilation on ASP.NET (sans MVC). Unfortunatelly it's very slow.



回答2:

If Roslyn compiler assemblies are not NGen'd, it may take some time to start VBCScompiler.exe(it references several large managed assemblies and it takes time to JIT them). To reduce the JIT period, you can NGEN all the Rsolyn assemblies on the machine. Also you can find some help info from this blog.