28
votes

The first call to our API is always extremely slow. For example, below demonstrates the CPU usage and time it takes for the first call to complete:

CPU usage

The first call can take up to 30 seconds and eats almost 100% CPU. Call 2 and 3 take 200ms (as they should). After recycling the application pool, it will do the same thing with the first call.

I've read a bit about IIS "warm-up" and done the following, but nothing has changed:

IIS 8 Application Initialization is installed:

IIS 8 Application Initialization

I have the following set in IIS:

  • Set Start Mode to AlwaysRunning:

AlwaysRunning

  • Set the Recycling Timeout to 0:

Recycling Timeout

  • Set the Idle Time-out to 0:

Idle Time-out

  • Set Preload Enabled to true on the site:

Preload Enabled

I am actually setting these in code in RoleEntryPoint.OnStart().

using (var serverManager = new ServerManager())
{
    serverManager.ApplicationPoolDefaults.ProcessModel.IdleTimeout = TimeSpan.Zero;

    foreach (var application in serverManager.Sites.SelectMany(x => x.Applications))
    {
        application["preloadEnabled"] = true;

    }

    foreach (var applicationPool in serverManager.ApplicationPools)
    {
        applicationPool.AutoStart = true;
        applicationPool["startMode"] = "AlwaysRunning";
        applicationPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
        applicationPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;

    }

    serverManager.CommitChanges();
}

I am almost certain that Entity Framework could be the culprit:

  • We are generating models from around 100 tables in a EDMX model "designer".

  • We are generating precompiled views generated by EF Power Tools.

  • The following initialization is running in Application_Start():

    using (var context = new MyContext())
    {
        context.Database.Initialize(false);
    }
    

I don't have these "initialization" problems when debugging.

The following tech is being used:

  • .NET 4.5.1
  • ASP.NET Web Api 2
  • Entity Framework 6.1.1
  • IIS 8 (Azure Web Role)
  • Unity 3.5

Can anyone provide me with any other ideas or suggestions?

1
Did you set preloadEnabled="true" in the applicationHost.config file for the web application?afrazier
@afrazier: Yes, that is set to true by the startup code.Dave New
Did you comment out the EF initialization code to see if the spike occurs?Avner
Please, add the settings to the .config file instead of setting them by code. To set them by code you need the application to run. You'd rather have them with the right setting from the starts. Additional note: have you tried logging the different steps of the strat-up to get usre they're running whenever the server restarts?JotaBe
@davenewza Your code should do it. When you call Initialize, the DB initialization and seeding is executed. But there is no documentation that warranties that the model (views) is loaded into memory. Perhaps (I only suppose it) the model isn't loaded until it's needed. So, you could also run a simple query inside the DB initializer to ensure this to happen.JotaBe

1 Answers

5
votes

Not sure if anyone has addressed this yet, but I've learned about some performance issues arising on the initial startup of Entity Framework. Julie Lerman discussed this in her Pluralsight course on Entity Framework, and is also alluded to in the following article excerpt from Microsoft:

One of the biggest drags on performance is the startup time involved with the first use of a context in an application process. You can do a lot to improve that startup time, though. Hopefully you’ve already learned these tricks from my own writing or other resources, such as the MSDN doc on performance considerations at bit.ly/3D6AiC.

A startup step that often hampers performance is the view gener­ation of mapping views, where EF creates the relevant SQL to query against each of the entity sets in the model. These views get leveraged as your app runs so that for certain queries, EF doesn’t have to work out the SQL on the fly. View generation happens whether you created your model with the EF Designer or with Code First. You can pre-generate these views and compile them into the application to save time. http://msdn.microsoft.com/en-us/magazine/dn532202.aspx

Here it seems she's not just talking about the 'initial load' but the actual first use of a context. I'd to a quick search for Julie Lerman and Entity Framework performance issues. I noticed similar slowness when making the initial calls to my Web API. Every call after the first was significantly faster. I personally haven't found it to be too awful, so I'm ignoring it (for now). However I do find it interesting that it doesn't occur in debug mode. Sorry if you've already explored these options, but I hope this helps a little.