In one of our ASP.NET Core services, we noticed that the memory is increasing after every request. It is reaching about 2GB in 2 days.
I tried to investigate the issue and I discovered that the issue is (probably) with the garbage collector that it is not getting triggered.
To make investigation easier, I tried to see how things are with a simple Web API app (Dotnet Core version 2.1 created from Visual Studio template, in Debug & Release/ Self contained & IIS Express)
This brand new app has the same issue. Memory goes up for every request and never gets released as shown in the image below.
In the case if the system is low in memory, GC is getting triggered but the memory never goes down. Is this normal?
Because this is very strange, I did the same test with a simple ASP.NET on Framework 4.6. Memory is released.
This is very strange and not acceptable. Can anyone please explain to me what's happening with ASP.NET Core memory?
Edit:
As requested, here is my code, a very basic ASP.NET Core generated from Visual Studio:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseMvc();
}
}
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
}
ASP.NET Core apps should be designed to process many requests simultaneously. Asynchronous APIs allow a small pool of threads to handle thousands of concurrent requests by not waiting on blocking calls. Rather than waiting on a long-running synchronous task to complete, the thread can work on another request.
Application level singletons generally migrate to generation 2. When an ASP.NET Core app starts, the GC: Reserves some memory for the initial heap segments. Commits a small portion of memory when the runtime is loaded.
Use Cache This is how caching saves time and improves the overall performance; reducing the server calls again and again. You can do client-side, server-side, or client/server-side caching. ASP.NET Core provides different caching such as caching In-Memory, Response caching, Distributed caching, etc.
I don't know if you ever found a solution but I was having the very same issue with my asp.net core 5.0 app. The solution DarthVader mentioned in the comments has worked for me. Just added the following part in the project file:
<PropertyGroup>
<ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With