Use DbContextPooling to improve the performance: .Net Core feature

DBContext Pooling improves the perfromance

You can find all .Net core posts here.

I have seen many awesome and new features sailed with ASP .Net Core 2.1. I have written a post for ASP Net Core 2.1 features which you can find here.

In this post, we will see one awesome EF Core 2.1 feature which is DBContext pooling.

There is not much written on the Internet about this awesome feature so thought to share this feature developed by the .Net Core team.

Let us first see how DbContext behaves before .Net Core 2.1.

AddDbContext

If you are familiar with .Net Core, then you might be knowing AddDbContext method. This method is used to inject dependency of DbContext into your controller and it should be written in the Startup.cs class. To know more about DbContext check here.

You can have a look at the code sample for Code First approach where AddDbContext is used in the Starup.cs class here. Blog Post for the Code first is here.

We use AddDbContext in Startup.cs class as below:


services.AddDbContext<EmployeeContext>(options => options.UseSqlServer(connection));

So in case of AddDbContext, a new instance will be created for each request and would get disposed once the work is done.

db3

As you can see above, new contexts are getting created for each request.

That is still fine but if there are more than 1k requests – 1k times object will be created and disposed, unless you have made it a Singleton. Creating and disposing of so many objects may impact the performance.

How DbContextPooling can help?

In simple words, using DbContextPoolinga pool of reusable instances can be created. So instead of creating a new instance every time, the code will first check if there is an instance available in the pool.

db4

As you can see in above picture, if there are contexts available then those contexts will be used first instead of creating new contexts everytime.

This will reduce the number of contexts created for each request.

Also instead of disposing of the instances completely, what it does is that it returns to the pool and resets the instance to its default state. Thus the context instance can be reused in the future.

How to use DbContextPooling?

It is quite simple, just add pool after AddDbContext as shown below:


services.AddDbContextPool<EmployeeContext>(options => options.UseSqlServer(connection));

As you can see above:

  • AddDbContextPool accepts the lambda expression defining the connection string
  • One more parameter is the integer containing the value of the maximum number of instances in the DbContext pool
  • The default value is 128
  • Instead of disposing of the instances completely, what it does is that it returns to the pool and resets the instance to its default state

Performance Test

You might be wondering how much performance improvements can be achieved with this?

.Net Team has created a small POC to measure the performance using DbContextPooling and without using DbContextPooling which you can find here.

The program runs a benchmark test that measures throughput (requests/second) of a simple web-like query scenario.

This application generally runs for 10 seconds and measures:

  • Context creation per Second
  • Request per Second
  • Total Context creation
  • Average request per second

Let us first run the application using AddDbContext without Pooling.

Below is the result:

db1

As you can see:

  • new Context instances are created every second and getting disposed
  • Total Context creation almost 19k+ in 10 seconds
  • Average requests per second – 1839

Now let us run the application using AddDbContextPool with pooling.

Below is the result:

db2

Wow, the difference is visible.

As you can see:

  • The application is not creating new Context instance in each request because the application is reusing the older instances
  • Only 32 contexts created in 10 seconds
  • Average request per second has been increased to 2285

Final result

As we saw above, using DbContextPooling, the number of executables dramatically dropped and the response ability of the program has also been upgraded by about 20% due to the reduced connection overhead in the database.

As the average number of requests are increased per second, the application can process the requests faster than it was processing before.

Note that it is a very small POC and the result may vary every time but when you would use pooling in the larger application then performance differences would be visible for sure.

Hope it helps.

6 thoughts on “Use DbContextPooling to improve the performance: .Net Core feature

    1. when i apply Services.AddDbContextPool then error occur .
      An Error is :
      ArgumentException: Expression of type ‘Microsoft.EntityFrameworkCore.DbContextOptions`1[DAL.Data.SqyBeatsContext]’ cannot be used for constructor parameter of type ‘Microsoft.EntityFrameworkCore.DbContextOptions`1[DAL.Data.DeveloperCrmContext]’
      Parameter name: arguments[0]

      Like

  1. This just solved a weird dbContext early disposal issue I was having. Couldn’t figure out why the context was getting disposed, even creating a copy to use for the method was getting disposed before it could be used. No idea why. Anyway, DBContextPool just fixed it and it feels faster in general. Thanks Neel!

    Like

Leave a comment