SOLVED

Why is my ASP.Net Web API piling up memory?

%3CLINGO-SUB%20id%3D%22lingo-sub-2959475%22%20slang%3D%22en-US%22%3EWhy%20is%20my%20ASP.Net%20Web%20API%20piling%20up%20memory%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2959475%22%20slang%3D%22en-US%22%3E%3CP%3EHi%20everyone%2C%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EI%20have%20a%20very%20simple%20MVC%20web%20api%20with%20a%20single%20controller%20that%20currently%20does%20nothing%20but%20returning%20a%20value.%20I%20am%20publishing%20it%20in%20VS2022%20Preview%201%20into%20a%20single%20file%2C%20so%20I%20get%20an%20.exe%20as%20an%20output.%20So%20far%20so%20good.%20That%20all%20seems%20to%20work%20fine.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EI%20have%20a%20C%2B%2B%20application%20that%20is%20communicating%20with%20that%20Web%20API%20and%20is%20starting%20it%20in%20an%20own%20process.%20Basically%20my%20test%20is%20calling%20an%20endpoint%20of%20the%20API%20every%20250ms%20and%20what%20I%20noticed%20is%20that%20this%20fills%20up%20my%20memory%20(slowly%20but%20constantly).%20Starting%20with%2016MB%2C%20after%20an%20hour%20the%20processs%20has%20swallowed%20around%2090MB%20of%20RAM.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3ECan%20anybody%20please%20tell%20me%20why%20is%20that%3F%20I%20am%20lost.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHere%20is%20the%20complete%20code%20of%20the%20Web%20API%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3E%2F%2F%20My%20Controller%0A%20%20%20%20%5BApiController%5D%0A%20%20%20%20%5BRoute(%22%5Bcontroller%5D%22)%5D%0A%20%20%20%20public%20class%20TestController%20%3A%20ControllerBase%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20Calling%20this%20endpoint%20every%20250ms%20from%20my%20C%2B%2B%20application%20via%20http%0A%20%20%20%20%20%20%20%20%5BHttpGet(%22buttonstate%22)%5D%0A%20%20%20%20%20%20%20%20public%20int%20GetButtonState(%5BFromQuery%5D%20string%20path)%0A%20%20%20%20%20%20%20%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20return%200%3B%20%0A%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%7D%0A%0A%2F%2F%20My%20startup%20class%0A%20%20%20%20public%20class%20Startup%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20Startup(IConfiguration%20configuration)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Configuration%20%3D%20configuration%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20public%20IConfiguration%20Configuration%20%7B%20get%3B%20%7D%0A%0A%20%20%20%20%20%20%20%20public%20void%20ConfigureServices(IServiceCollection%20services)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20services.AddControllers()%3B%20%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20public%20void%20Configure(IApplicationBuilder%20app%2C%20IWebHostEnvironment%20env)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(env.IsDevelopment())%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20app.UseDeveloperExceptionPage()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20app.UseRouting()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20app.UseEndpoints(endpoints%20%3D%26gt%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20endpoints.MapControllers()%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%2F%2F%20My%20program%0Apublic%20class%20Program%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20static%20void%20Main(string%5B%5D%20args)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20CreateHostBuilder(args).Build().Run()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20public%20static%20IHostBuilder%20CreateHostBuilder(string%5B%5D%20args)%20%3D%26gt%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Host.CreateDefaultBuilder(args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.ConfigureWebHostDefaults(webBuilder%20%3D%26gt%3B%20%7B%20webBuilder.UseStartup%3CSTARTUP%3E()%3B%20%7D)%3B%0A%20%20%20%20%7D%3C%2FSTARTUP%3E%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2959475%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EASP.Net%20Core%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2960779%22%20slang%3D%22en-US%22%3ERe%3A%20Why%20is%20my%20ASP.Net%20Web%20API%20piling%20up%20memory%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2960779%22%20slang%3D%22en-US%22%3EHave%20you%20tried%20launching%20it%20without%20debugger%3F%20Maybe%20with%20dotnet%20run%20command.%20Is%20the%20behaviour%20same%20even%20then%3F%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2963354%22%20slang%3D%22en-US%22%3ERe%3A%20Why%20is%20my%20ASP.Net%20Web%20API%20piling%20up%20memory%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2963354%22%20slang%3D%22en-US%22%3EIf%20you're%20calling%20it%20ever%20250ms%2C%20it's%20likely%20not%20quiet%20enough%20for%20the%20Garbage%20collector%20to%20fire%20up.%20And%20with%2090mb%2C%20it%20likely%20isn't%20pushing%20enough%20memory%20pressure%20(that's%20still%20tiny)%20to%20force%20the%20Garbage%20collector.%3C%2FLINGO-BODY%3E
Occasional Contributor

Hi everyone,

 

I have a very simple MVC web api with a single controller that currently does nothing but returning a value. I am publishing it in VS2022 Preview 1 into a single file, so I get an .exe as an output. So far so good. That all seems to work fine.

 

I have a C++ application that is communicating with that Web API and is starting it in an own process. Basically my test is calling an endpoint of the API every 250ms and what I noticed is that this fills up my memory (slowly but constantly). Starting with 16MB, after an hour the processs has swallowed around 90MB of RAM.

 

Can anybody please tell me why is that? I am lost.

 

Here is the complete code of the Web API:

 

 

// My Controller
    [ApiController]
    [Route("[controller]")]
    public class TestController : ControllerBase
    {
        // Calling this endpoint every 250ms from my C++ application via http
        [HttpGet("buttonstate")]
        public int GetButtonState([FromQuery] string path)
        {                  
            return 0; 
        } 
    }

// My startup class
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers(); 
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();             
            });
        }
    }

// My program
public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
    }

 

 

 

6 Replies
Have you tried launching it without debugger? Maybe with dotnet run command. Is the behaviour same even then?
best response confirmed by SamXion (Occasional Contributor)
Solution
If you're calling it ever 250ms, it's likely not quiet enough for the Garbage collector to fire up. And with 90mb, it likely isn't pushing enough memory pressure (that's still tiny) to force the Garbage collector.
The VS publishing function is always compiling in Release mode so that cannot be it. Also, actually when running the API in debug mode, this memory piling does NOT occur. Oo

Thanks. That was also my initial thought, so I was calling GC.Collect() at the end of each request (i.e. before return 0;), simply to force the gc to free all generations but...no change and no memory freed. RAM still piling up. :\

It seems strange that this does not happen when running the API in debug mode from inside of VS. This gives me the impression that it might not be the API itself maybe? Maybe it's how I spawn the process (doing this from C++ via Qt and QProcess).

Hmm, even if I start the API manually (double-clicking the executable), this memory piling occurs. So it's not due to the process spawning itself either.
Ok, I have to apologize and row back here. Even though I called GC.Collect(), I just noticed that I was running an older build that did NOT call the garbage collection. Running the latest build does indeed get rid of the memory piling.

So thanks for the help! This resolves my issue. :)