question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

What's the performance benefit of pooling DbContexts

See original GitHub issue

Since EF Core 2.0 it supports pooling of DbContext instances. I can find statements from @anpete such as:

The new method introduces a few limitations on what can be done in the OnConfiguring() method of the DbContext but it can be adopted by many ASP.NET Core applications to obtain a performance boost.

Implying that pooling give a performance boost, while @ajcvickers states:

The point of DbContext pooling is to allow reuse of DbContext instances from a pool, which for certain scenarios can result in a performance boost over creating a new instance each time. This is also the primary reason for connection pooling in ADO.NET, although the performance boost for connections will be more since connections are generally a more heavyweight resource.

Implying that DbContext pooling is not as significant as connection pooling.

I couldn’t find any analysis or benchmarks of the actual performance improvement this brings. To my knowledge, the creation of DbContext instances is really light. A small local test showed that I could make over 600,000 instances a second on a single thread.

I found this question from @davidroth:

Out of curiosity: Can you share some benchmarks about this improvement?

Unfortunately, the question was ignored.

What does cause a performance hit when DbContext instances are not reused? Can we find a publically accessible benchmark that shows what the benefit of pooling is and especially an alalysis of what is causing the bottleneck without the reuse of DbContext instances?

Thanks in advance.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:15
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

17reactions
ajcvickerscommented, Oct 20, 2017

@dotnetjunkie DbContext initialization is a two-part process. Creating the instance itself does minimal work–basically just initializing any DbSet properties. This means creating a DbContext that is not used does not add significant overhead, which is important for scenarios such as a controller that may need to access the database but often does not–just injecting/creating the instance should not be a perf issue.

The first time the context is used, for a query, to track something, etc., there is a second lazy initialization that happens. This involves loading some services from EF’s internal D.I. that are scoped to the same lifetime as the context. Not all services are like this–many are singletons that are shared between all context instances. Also, not all services are initialized at this time–services that may not be needed can be loaded lazily–however, we have seen that this is sometimes more expensive than loading immediately due to the way the D.I. system compiles constructor calls.

The second initialization step is also not really slow, but DbContext pooling means that instead of doing this step, an existing pooled instance is used instead, with resetting of the service internals. This is less flexible–each context instance in the pool must be configured the same way so that the same set of services with the same configuration is correct each time.

Whether or not this really shows a measurable difference in your app depends a lot on how much else the context is doing. Where it works well is for simple, no-tracking queries where very little other work is being done. As soon as the context starts to do more work, the relative amount of time saved by pooling is much less.

It’s also worth keeping in mind that there is additional initialization which is not bound to a particular context instance. So, for example, the first time a model is used by any context instance there will be a hit while the model is built and cached. Likewise for the first time a query is executed, and so on. Pooling will not have any impact on these things.

Hope that helps!

11reactions
smitpatelcommented, Sep 14, 2018

@gius - All services including ChangeTracker are reset when the DbContext is returned to the pool. So whenever you get a context from pool, it is same as what it would be if you re-initialize it (except for few limitations).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Advanced Performance Topics
DbContext pooling. A DbContext is generally a light object: creating and disposing one doesn't involve a database operation, and most ...
Read more >
Use DbContextPooling to improve the performance: .Net Core ...
In simple words, using DbContextPooling – a pool of reusable instances can be created. So instead of creating a new instance every time,...
Read more >
DbContext & DbcontextPool in ef-core
The pooling mechanism ensures that, when a DI scope ends, the DbContext is 'cleaned' and brought back to the pool, so it can...
Read more >
Entity Framework DbContext pooling performance benchmark
Context pooling allows you to pay context setup costs only once at program startup. There's a simple benchmark on the Advanced Performance ...
Read more >
Best Practices in Using the DbContext in EF Core
With context pooling, context setup costs are only incurred once at the program startup time rather than every time the application runs. When ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found