Description
Our unpooled DbContext instantiation has become heavy enough that using pooling is a really idea in the real world, not just in high-perf TechEmpower-like scenarios. The benchmark in dotnet/efcore#27694 (comment) does a simple non-tracking query which retrieves a simple empty row:
Method | Rows | Mean | Error | StdDev | Median |
---|---|---|---|---|---|
EFCore | 1 | 974.1 us | 44.82 us | 131.46 us | 960.2 us |
EFCorePooled | 1 | 479.4 us | 31.75 us | 93.11 us | 444.4 us |
That's half a millisecond of absolute time spent setting up various services in memory, or a 50% improvement in relative terms (note these results are against localhost, so the gap would be less significant as the database is farther away). This again makes EF Core slow out-of-the-box, requiring extra knobs and knowledge to make it perform well, and the discoverability of context pooling isn't great.
We could add an analyzer which identifies non-pooled APIs and warns, guiding people towards the pooling APIs instead. For example, ServiceCollection.AddDbContext would cause a warning, pointing towards AddPooledDbContext. For non-DI use, we could identify constructors on the user's DbContext-inherited type (which call the base constructor), and flag on them.