0

I have an ASP.NET Core 8.0 application where I want to move some controllers into a module (separate project). To accomplish this I had to update the startup from:

services.AddControllersWithViews()
        .AddRazorRuntimeCompilation();

to:

var assembly = typeof(HomeController).Assembly;
services.AddControllersWithViews()
        .AddApplicationPart(assembly)
        .AddRazorRuntimeCompilation(options =>
            {
                options.FileProviders.Add(new EmbeddedFileProvider(assembly));
            });

This works fine when I start the application (it starts and all endpoints/views are available as before), but I have a problem when running the tests suite.

The tests run with xUnit and use a base class to setup an instance of the service and then uses API calls and a browser instance to call the endpoints on the service. For each test a new instance of the service is initialized. This worked fine before the change with a memory usage of around 800MB, but after the change the memory usage went up to 13GB. It is a testsuite of 200 tests and during the run gradually the memory increases. So it looks like, after the change, some memory is not released after each test.

Some things I have tried:

  • Made assembly a static field
  • Tried all sorts of different orders of calling these methods
  • Tried adding dispose methods on the service host
  • Tried to profile memory usage, this doesn't teach me much, but in the memory snapshot I see a lot of "Razor Compilation" stuff coming back. But it doesn't give a clear indicator. I see there are a lot of "instances" still active in memory:

screenshot memory usage

I am very much at a loss about how this change could cause a memory leak, so any leads or ideas of things to try would be much appreciated.

2

1 Answer 1

0

Thanks to @Guru Stron's comment I tried the following changes, I removed AddRazorRuntimeCompilation so the code now is as follows:

var mvcBuilder = services.AddControllersWithViews()
    .AddApplicationPart(assembly);

if (Options.IsDevelopment)
{
    mvcBuilder.AddRazorRuntimeCompilation();
}

services.Configure<MvcRazorRuntimeCompilationOptions>(options =>
{
    options.FileProviders.Add(new EmbeddedFileProvider(assembly));
});

Another change I made was, updating the "Module" project to be a Web project:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <OutputType>Library</OutputType>

Instead of what it was before:

<Project Sdk="Microsoft.NET.Sdk">

I think that is what made the difference, because when I did this I actually got a compile error (namespace to missing package) in one of the Views. And the memory usage for the 200 tests is now back to what it was before.

So either one of these changes resolved the issue, but both are probably best practice for this scenario anyway.

Not the answer you're looking for? Browse other questions tagged or ask your own question.