Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High memory usage for unit tests #548

Closed
ArnaudB88 opened this issue Nov 3, 2020 · 3 comments
Closed

High memory usage for unit tests #548

ArnaudB88 opened this issue Nov 3, 2020 · 3 comments

Comments

@ArnaudB88
Copy link

Hi,

We recently migrated from StructureMap to Lightinject for a big solution. This solution has +1500 unit tests and we use mstest as testing framework.

With structuremap, we used one single container for all unit tests and did the necessary overrides (mocks/stubs) before and after each test. Since Lightinject doesn't support this, we create and dispose a container for each test.
We have a dbcontext for a connection to the database, so this is registered as scoped. Therefore we create a scope on the container for each unit test and retrieve instances from that scope which are needed for the test.

Some (pseudo)code:

protected IServiceContainer Container;
protected Scope ServiceFactory;

[TestInitialize]
public void Initialize()
{
    Container = new ServiceContainer();
    // assembly scanning for registrations
    foreach(var dllFilePath in Directory.GetFiles(AppContext.BaseDirectory, "MyCompany.MySolution.*.dll"))
    {
        var assembly = Assembly.LoadFrom(dllFilePath);
        Container.RegisterAssembly(assembly);
    }
    //Create Scope
    ServiceFactory = Container.BeginScope();

    //Override default registrations with subbed/mocked variants
    Container.Register<IBar, BarStubbed>();
}
[TestCleanup]
public void CleanUp()
{
    ServiceFactory.Dispose();
    Container.Dispose()
}

[TestMethod]
public async Task ExecuteAsync_Should_Work()
{
    var dto = new FooDto();

    await ServiceFactory.GetInstance<IFoo>().ExecuteAsync(dto);
}

Problem:
When running all +1500 unit tests, the memory usage raised to 9GB. This gave errors in devops because the azure devops build agents only have 7GB of memory.

I began to investigate and came to following conclusions:

  • 1 container for all unit tests gave a constant memory usage (but tests failed because overrides after first test were not possible anymore)
  • 1 container per unit test resulted in a linear raising memory usage (up to 9GB)
  • limiting assembly scanning for container registrations to projects which only have a composition root (6) instead of all our projects in the solution (17) resulted in less memory usage (-38%)
  • not using a scope but only a container resulted in less memory usage (-85%). The scoped registrations were overridden as singleton since each unit test has a single scope.

Some timings (averages):

duration (min) memory (GB) explanation
1 container per test 11.5 9.2 each test: 1 container, 1 scope, assembly scanning 17 projects
limit regs 7.9 5.7 limit assembly scanning to 6 projects, each with composition root
no scope 8.9 1.4 no scope, only container, override scoped registration as singleton
no scope + limit regs 7.6 1.3 combination of both above
1 container for all 1.6 0.2 1 shared container for all tests, contant memory usage, failing tests

Is it possible to investigate this? Currently I'll change the code so we don't use a scope in our unit tests, but the linear increasing memory is still a concern for me.
Thanks!

@seesharper
Copy link
Owner

Hi @ArnaudB88. This might suggest a memory leak related to the scope or services registered as scoped within the container.
Would it be possible for you to create a minimal repro "proving" the memory leak?

@ArnaudB88
Copy link
Author

I will see if it's possible to make a solution which illustrates this behavior. It's not easy to reproduce problems of a big solution in a simple small solution.
If you want, I can always provide other info (eg. screenshot of memory snapshots)

@ArnaudB88
Copy link
Author

This issue was solved by the same fix for issue #549 .
(Not using the static container for resolving instances)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants