4

We have about 200 DLLs (150MB+ in size) in our ASP.NET MVC 3.0 app, and the startup time in development, is about ~60 seconds.

Every time we modify a project and rebuild it to get a new DLL to be deployed, once we chuck that new DLL into "webapp\bin" folder, IIS re-JIT every other DLLs as well (which has not changed) and this maxes out 1 CPU core and takes about 60 seconds.

What can I do to speed this loading time up?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
user5133888
  • 139
  • 1
  • 11
  • 1
    The obvious question is "How do you have 200mb of monolithic code?". What makes up the 200mb? Can you break it out? (to resources stored as loose files, other services, out-of-process components, GAC'd components, lazy loading, etc...) – Mitch Jun 04 '16 at 19:47
  • It is not monolithic, but simply there are 150MB+ worth of 200+ DLLs. Was hoping to be able to tell ASP.NET, hey most DLLs (but one DLL) haven't changed, don't re-JIT them on startup – user5133888 Jun 04 '16 at 19:53
  • I'd strongly recommend to use [Roslyn](https://roslyn.codeplex.com/) software to check up your code for issues. – Maciej Los Jun 04 '16 at 19:54
  • I suppose I can find a way to lazy load some DLLs – user5133888 Jun 04 '16 at 19:55

2 Answers2

4

The easiest way is not to put all the application DLLs into the webapp\bin which is watched by IIS. You can utilize dynamic DLL load from a custom location using the AppDomain.AssemblyResolve Event.

For that you will need to register an HttpModule in the web.config

</configuration>
  </system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="CAssemblyResolveHttpModule"/>
      <add name="CAssemblyResolveHttpModule"
           type="CAssemblyResolveHttpModule"/>
    </modules>
  </system.webServer>
</configuration>

And an implementation for it:

public class CAssemblyResolveHttpModule : IHttpModule
{
    public void Init(System.Web.HttpApplication iContext)
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }

    private Assembly CurrentDomain_AssemblyResolve(
        object iSender,
        ResolveEventArgs iArgs)
    {
        return Assembly.LoadFrom(...);
    }
}

Besides that you can prevent IIS from recycling the ASP.NET Application when bin folder changes via IIS settings:

Can I prevent IIS from recycling if /bin changes It is simple:

In the Application Pool > Advanced Settings > Recycling section, set the Disable Recyling for Configuation Changes to True.

If you move most of your DLLs out of the app bin folder the IIS application pool recycling will take not more than a few moments. In order to catch up another new DLL version you will need to recycle the application pool.

If you still wish to avoid app pool recycling altogether you can use the strategy of a custom app domain pool. Here you can get code samples: Create custom AppDomain and add assemblies to it

Community
  • 1
  • 1
Zverev Evgeniy
  • 3,643
  • 25
  • 42
  • Thanks Zverev, so in theory I can rebuild a DLL and put it outside of webapp\bin folder, and use AppDomain.AssemblyResolve event to load the DLLs dynamically, so IIS does not have to re-JIT the whole webapp\bin folder? – user5133888 Jun 04 '16 at 20:00
  • @user5133888 Correct. This is what I was suggesting. I am using this strategy for years now. Keep in mind that such Assembly.LoadFrom will block the assembly file for the lifespan of the AppDomain that loaded the DLL. – Zverev Evgeniy Jun 04 '16 at 20:04
  • once a DLL is loaded, and then it is rebuilt, how can I tell ASP.NET to reload that DLL, other than recycling the AppPool (as that DLL is located outside the webapp/bin) ? – user5133888 Jun 05 '16 at 11:24
  • 1
    AppPool recycling has to be done. Other way the previous DLL version will be used for request handling. The idea is that when you place all your DLLs out of bin folder, the recycling does not take more than a few moments. If you really need to avoid app pool recycling for some reason, you will have to organize custom app domain pool and handle your requests there: http://stackoverflow.com/questions/17225276/create-custom-appdomain-and-add-assemblies-to-it – Zverev Evgeniy Jun 05 '16 at 11:45
0

If most of the DLLs do not get used immediately, you can place them in the GAC. This prevents ASP.Net from loading them on startup and also elides signing verification when they are actually loaded.

Mitch
  • 21,223
  • 6
  • 63
  • 86