Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ASP Net Core 2.2 do not release memory?

I'm testing ASP Net Core 2.2 using default project made from:

Visual Studio > File > New > Project > ASP NET Core Web Application > Next > Create. Press IIS Express button on interface and automatically go to https://localhost:44356/api/values

Edit: The point is, I'm testing ASP Net Core in case of brute force spamming from people.

I have only modified this:

        [HttpGet]         public ActionResult<IEnumerable<string>> Get()         {             return new string[] { "value1", "value2" };         } 

Edit: to this, I edited my code to reasonable test, producing minimal reproducable example

// GET api/values  [HttpGet] public ActionResult<IEnumerable<Post>> Get() {     // Testing for brute force     return Enumerable.Range(0, 100).Select(x => "Example Value").ToList(); } 

The starting Process Memory is 80 MB.

However, when I tried refreshing the page, the starting memory keeps coming up: edited test

Edit: Turns out this issue has been there from 2 years ago, with no solution, and with Real Life Example Experience, https://github.com/aspnet/AspNetCore/issues/1976

I'm pretty sure that yellow arrow means GC is working correctly, but my process memory usage isn't coming down every request. I'm not sure if this is a feature or bug from ASP Net Core, I expected it to go down after request / did not increase everytime a user GET the /values

Edit: I don't want people dangerously spamming my app and it starting to crash down because memory leak. And I'm afraid to use Net Core for my company if this solution is not fixed yet.

Why ASP Net Core 2.2 do not release memory?

I have tried testing in two different laptop, the result is same.

Edit: My colleague also have this problem.

Edit: I have tried using dot net core v2.1, the result is same.

I have tried GCCollect(); the result is same.

old image ref.

Starting Process Memory

Process Memory keeps coming up

like image 406
Kevin Tanudjaja Avatar asked Aug 21 '19 12:08

Kevin Tanudjaja


People also ask

Is .NET Core 2.2 supported?

NET Core 2.2 is supported until December 23, 2019. After that time, . NET Core patch updates will no longer include updated packages of container images for . NET Core 2.2.

Which ASP.NET Core no longer depends on the system?

Fast: ASP.NET Core no longer depends on System. Web. dll for browser-server communication. ASP.NET Core allows us to include packages that we need for our application.

What takes care of memory management in dotnet?

Garbage Collector (GC) is the part of the . NET framework that allocates and releases memory for your . NET applications. When a new process is started, the runtime reserves a region of address space for the process called the managed heap.


2 Answers

ASP.NET Core can appear to use more memory than it should because it's configured to use Server GC by default (as opposed to Workstation GC). For a discussion of a similar concern see here. In theory, the application should be able to reduce its memory footprint when your server faces a memory pressure.

More on this topic in this MSDN doc and Github CoreCLR doc.

To see if it's indeed Server GC that causes the additional memory consumption, you can set GC strategy to workstation in your csproj file:

<PropertyGroup>      <ServerGarbageCollection>false</ServerGarbageCollection> </PropertyGroup> 
like image 57
scharnyw Avatar answered Oct 03 '22 22:10

scharnyw


!!!LAST EDIT: THIS SOLUTION IS NOT THE BEST WAY, SOME MIGHT SAY THIS IS A TERRIBLE SOLUTION... I RECOMMEND THE ANSWER BELOW!!!

I was struggling with the same issue. After a little research i found that .NET Core allocating new memory space if it can. It will be released if it is necessary, but this release is more resource demanding than the other releasing, because you have to use the GC this way:

GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); 

My solution was to create a middleware:

using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks;  namespace RegisterValidator {     public class GCMiddleware     {         private readonly RequestDelegate _next;          public GCMiddleware(RequestDelegate next)         {             _next = next;         }          public async Task Invoke(HttpContext httpContext)         {             await _next(httpContext);             GC.Collect(2, GCCollectionMode.Forced, true);             GC.WaitForPendingFinalizers();         }     } } 

EDIT: this middleware will provide a GC.Collect after every call.

And register it in the Configure() method in Startup.cs:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider service, ILoggerFactory loggerFactory)     {          app.UseMiddleware<GCMiddleware>();         if (env.IsDevelopment())         {             app.UseDeveloperExceptionPage();         }         else         {             app.UseHsts();         }          app.UseStaticFiles();         //app.UseHttpsRedirection();         app.UseMvcWithDefaultRoute();          app.Run(async (context) =>         {             await context.Response.WriteAsync("\"No ");          });     } 

Maybe there is another solution but I haven't found it yet. I hope it helps.

Edit: If you aren't sure that the memory usage is because there is a huge amount of allodated space of some other issue you can use dotMemory that will profile your memory usage with more detail than your Visual Studio.

like image 27
turanszkik Avatar answered Oct 04 '22 00:10

turanszkik