Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reduce memory usage for .NET Core docker containers?

We are running .NET Core 1.1 containers on Docker/Ubuntu, hosting Web APIs. The containers are based on microsoft/aspnetcore:1.1.2 with the binaries published for Ubuntu x64 platform and copied in when the image is built, as simple as it gets.

Our Web APIs are also very simple at the moment, at most a handful of controllers pulling data from SQL Server. They do no significant caching or anything unusual, but when running use anywhere from 500-900 Mb of RAM each. This is not due to memory leaks - the memory usage for each container is stable over time, varying up and down by 10-15Mb during usage.

This level of RAM use should be completely unnecessary - how can I reduce it?

I have reviewed the Docker container memory use question but it's different, and has no answer at this point.

like image 374
Peter Avatar asked Sep 05 '17 06:09

Peter


1 Answers

I've tried a couple of approaches to fix this, and had a response from the .NET Core team, so I'll document here in case it's useful for others.

1) I have has some success specifying memory limits on the Docker container command-lines using the flags, eg. --memory="200m" --memory-swap="500m"; this can be used to control memory usage and prevent the server from running out of memory unexpectedly, but what I've seen is that the memory required by the container does not reduce significantly, it just gets forced into swap, which degrades the performance of the API. I have not tried --memory="200m" --memory-swap="200m" (ie. no swap allowed) - I will do that when I have a chance, I suspect the API will throw an Out Of Memory exception, or be seriously degraded.

2) The best solution with .NET 1.1 (if you need to limit memory) seems to be to switch the GC to workstation mode by putting <ServerGarbageCollection>false</ServerGarbageCollection> in the .csproj file PropertyGroup section. In my case this drops memory usage to 80-100mb per container. Server Garbage Collection is designed to handle memory clean up during periods of massive concurrency, so this is probably not a good solution if you are building APIs or sites which experience this, but our APIs have small numbers of concurrent users, so it seems to work well.

Longer term, I got a useful response from @janvorli on the CoreCLR team. Apparently this problem is caused by a bug in the .NET Core GC which will be fixed in the upcoming 2.0.2 release. You can read the detail in this issue on the Github repo (search for "ettery").

like image 158
Peter Avatar answered Sep 26 '22 19:09

Peter