Skip to content

DB Context pooling with proxies resulting in memory issues in 8.0 RC2 #32267

@o-tto

Description

@o-tto

DB Context pooling with proxies enabled

Issue #25486 describes that this issue should be resolved in .NET 8 RC1. When comparing .NET7 with .NET8 RC2 no differences in memory handling are noticable.
When running the code below the process quickly passes the 1GB memory mark. When disabling proxies or using adddbcontext instead of pooling the memory usage is more consistent (as it should be after disposing the scope, I assume).

Code example

var testProcess = new TestSetup();
testProcess.InitializeServiceProvider();
await testProcess.QueryTest();

public class TestSetup
{
    private IServiceProvider _serviceProvider;
    public IServiceProvider InitializeServiceProvider()
    {
        var sc = new ServiceCollection();
        sc.AddDbContextPool<Context>(options =>
        {
            options.UseInMemoryDatabase("test").UseLazyLoadingProxies();
        });

        // For comparison (does not result in high memory usage)
        //sc.AddDbContext<Context>(options =>
        //{
        //    options.UseInMemoryDatabase("test").UseLazyLoadingProxies();
        //});

        _serviceProvider = sc.BuildServiceProvider();
        return _serviceProvider;
    }

    public async Task QueryTest()
    {
        await using ( var insertScope = _serviceProvider.CreateAsyncScope())
        {
            var insertScopeSp = insertScope.ServiceProvider;
            var insertScopeCt = insertScopeSp.GetRequiredService<Context>();
            for (var x = 1; x <= 10000; x++)
                insertScopeCt.TestModels.Add(new TestModel() {Id = x, Test = "test"});
            await insertScopeCt.SaveChangesAsync();
        }

        var i = 0;
        while (i < 100000)
        {
            i++;
            await using var scope = _serviceProvider.CreateAsyncScope();
            var sp = scope.ServiceProvider;
            var contextInstance = sp.GetRequiredService<Context>();
            var list = await contextInstance.TestModels.ToListAsync();
        }

        Console.ReadLine();

    }


    // DB Context
    public class TestModel
    {
        public long Id { get; set; }
        public string Test { get; set; }
    }
    public class Context : DbContext
    {
        public Context(DbContextOptions options) : base(options) { }
        public DbSet<TestModel> TestModels { get; set; }
    }
}

Memory snapshot comparison with Pooling only
image

image

Memory snapshot comparison with Pooling and proxies enabled
image

image

EF Core version:

    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-rc.2.23480.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0-rc.2.23480.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.0-rc.2.23480.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-rc.2.23480.1">

Database provider: InMemory
Target framework: 8.0
Operating system: Win-11
IDE: VS 2022 Preview 17.8.0 Preview 3

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions