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.
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.
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.
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 DbContextPooling – a 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.
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
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:
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:
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
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.