Memory leak in .NET 6 when adding a type resolver repeatedly
See original GitHub issueHi everyone,
After migration to .NET 6 I’ve noticed a high CPU usage which causing by memory pressure as GC runs more aggressively.
Analysing the coredump i’ve noticed a lot of Npgsql.NetTopologySuite.Internal.NetTopologySuiteTypeHandlerResolverFactory
objects stays in Gen 2, digging deeper i’ve found the GC root of those ones which is basically looks like this:
HandleTable:
00007FB6DB481378 (strong handle)
-> 00007FB5CC007C10 System.Object[]
-> 00007FB50C0C99C0 Npgsql.TypeMapping.GlobalTypeMapper
-> 00007FB50C0C9A00 System.Collections.Generic.List`1[[Npgsql.Internal.TypeHandling.TypeHandlerResolverFactory, Npgsql]]
-> 00007FB58C11F150 Npgsql.Internal.TypeHandling.TypeHandlerResolverFactory[]
-> 00007FB52FED6F98 Npgsql.NetTopologySuite.Internal.NetTopologySuiteTypeHandlerResolverFactory
Reproduce code is pretty simple:
- Create console app with Npsql provider inside
- Create sample DbContext and add it in startup
- Register NetTopologySuite using extension
.UseNetTopologySuite()
- in Program.cs build the Host, create an infinite loop which then just create the scope, and resolves DbContext
- Run code, and see how memory grows.
Full example: Startup.cs
services.AddDbContext<AppDbContext>(options =>
{
options.UseNpgsql("connectionstring", o => o.UseNetTopologySuite());
});
Program.cs
var host = CreateHostBuilder(args).Build();
while (true)
{
using var scope = host.Services.CreateScope();
scope.ServiceProvider.GetRequiredService<AppDbContext>();
}
Now let me deeply explain what’s wrong here:
- By default
.AddDbContext()
register DbContext with scoped lifetime, which is intentional and nothing wrong here. - Each time DbContext is needed - it’s resolved from SeviceProvider
- In order to resolve the service, it should call provided serviceFactory func to configure the DbContext options so each time DbContext is resolved, registration func is called for each particular ServiceScope
- Regisration func in our example is
(options) => options.UseNpgsql("connectionstring", o => o.UseNetTopologySuite());
.UseNetTopologySuite()
extension calls theNpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(parameters)
extension overGlobalTypeMapper
static singletone instance which is basicallyTypeMapping.GlobalTypeMapper.Instance
inside- The extension above calls
mapper.AddTypeResolverFactory(new NetTopologySuiteTypeHandlerResolverFactory(coordinateSequenceFactory, precisionModel, handleOrdinates, geographyAsDefault))
TypeMapping.GlobalTypeMapper.AddTypeResolverFactory()
listed here just inserts the newly created factory into internal list.- List - which is holding the factories is a property of static instance so it will continue referencing of all those created factories forever, adding new instance each time - scope is created and DbContext instance is resolved.
This issue is critical as it will affect all users under normal workloads with scoped DbContext (which is default) and using NetTopologySuite.
P.S. I can submit the PR fixing this if you have no time, but let’s agree on the proper place to fix this issue.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:9 (4 by maintainers)
Top Results From Across the Web
Find, Fix, and Avoid Memory Leaks in C# .NET: 8 Best ...
6. Use the Dispose pattern to prevent unmanaged memory leaks. Your .NET application constantly uses unmanaged resources. The .NET framework ...
Read more >Why EF core memory leak exception is solved by static ...
This can potentially lead to a memory leak if the query is executed repeatedly, because the expression tree and the Person objects it ......
Read more >Debug a memory leak in .NET Core
A memory leak may happen when your app references objects that it no longer needs to perform the desired task. Referencing said objects...
Read more >Fixing a memory leak in .Net Core - A Method to Madness
The memory leak becomes quite obvious : the memory consumption keeps on growing, until it reaches a threshold matching the server's specs. We ......
Read more >Unmanaged memory leaks in .NET
In either case, the first task is to detect which kind of memory is leaking and investigate the problem memory domain in more...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Good to hear, thanks and sorry that such a critical bug slipped into the release. We’ll release 6.0.1 soon, until then please continue using this patch build.
@thecodemonk great to hear, thanks! Yes, we definitely intend to release 6.0.1 within the next few days (working on some last fixes that need to get in). Please feel free to use the CI release in the meantime.