Efcore: "Warm up" method?

Created on 2 May 2019  路  3Comments  路  Source: dotnet/efcore

I'm setting up some Health Checks - specifically, some readiness checks for use with kubernetes. I want traffic to be routed to an instance only after it's gone through the EF Core "warmup" process.

I see the official EF Core health check calls context.Database.CanConnectAsync. I've extended this to at least cover that GetPendingMigrationsAsync returns an empty list, since if it doesn't, it can't really be considered ready.

I'd like to push this further to make sure it's all started up, i.e. the model is all loaded and the first query overhead is out of the way. What's the best way to do this? A call to context.Model.GetEntityTypes() or something? (This is a generic check at the moment, so I don't have access to any specific entity types or a solid context type)

closed-question customer-reported

Most helpful comment

@kierenj Some info that will hopefully help you decide what's appropriate in your case. Usually initialization falls into three broad categories:

  • Creating the DbContext instance

    • Some things happen at this point, such as initializing DbSet properties, but it's minimal and generally fast.

  • First use of the context instance

    • The internal service provider is built. (It is possible that this will happen again at some point if some configuration changes that needs a different internal provider--for example, using a different database provider.)

    • The model is built (It is possible that this will happen again at some point if a different context type is used, or for other conditions if the model cache key generation has been customized.)

    • Easiest way to trigger this phase is by accessing the model: _ = context.Model;

  • First time a given query is run

    • The query is compiled and cached

    • This could happen at any time a previously unseen query is encounted

There are also some one-off initializations to build accessor delegates and the like, but these should not have a huge impact.

My intuition is that initializing the model to get most of the "global" stuff cached is probably what you should do.

All 3 comments

@kierenj Some info that will hopefully help you decide what's appropriate in your case. Usually initialization falls into three broad categories:

  • Creating the DbContext instance

    • Some things happen at this point, such as initializing DbSet properties, but it's minimal and generally fast.

  • First use of the context instance

    • The internal service provider is built. (It is possible that this will happen again at some point if some configuration changes that needs a different internal provider--for example, using a different database provider.)

    • The model is built (It is possible that this will happen again at some point if a different context type is used, or for other conditions if the model cache key generation has been customized.)

    • Easiest way to trigger this phase is by accessing the model: _ = context.Model;

  • First time a given query is run

    • The query is compiled and cached

    • This could happen at any time a previously unseen query is encounted

There are also some one-off initializations to build accessor delegates and the like, but these should not have a huge impact.

My intuition is that initializing the model to get most of the "global" stuff cached is probably what you should do.

Perfect, thank you. :)

To others coming here: In a pretty clean setup, assigning context.Model as a warmup measure reduces my first query from 1500ms to 600ms, subsequent queries are < 50ms (10k rows non-tracked)

Was this page helpful?
0 / 5 - 0 ratings