dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.63k forks source link

Question: Process.PrivateMemorySize64 - Differences between Debian/Ubuntu vs Alpine based images #100760

Closed Baklap4 closed 1 month ago

Baklap4 commented 5 months ago

We wrote a healthcheck for aspnetcore webapi, but came to the conclusion that using PrivateMemorySize64 as "Memory Used in Bytes" doesn't match the graph we see in ElasticSearch Kibana (through metricbeat).

For our Alpine images the check and graph are aligned But once we use Debian/Ubuntu based images the check outputs a way higher value than it's actually showing in the graph

OS PrivateMemorySize64
Debian 11 75264000
Debian 12 75218944
Alpine 3.18 19591168
Alpine 3.19 19595264
Ubuntu 22.04 75218944

What's this big difference? Looking through the code they both use the cgroups memory.usage_in_bytes file

using System.Diagnostics;

namespace MemoryUsage
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            using var proc = Process.GetCurrentProcess();
            Console.WriteLine($"PrivateMemorySize64 -> {proc.PrivateMemorySize64}");
            proc.Dispose();
        }
    }
}

Running Container images

MichalPetryka commented 5 months ago

Alpine uses MUSL libc while Debian and Ubuntu use GNU libc, cgroups must behave differently between those two.

janvorli commented 5 months ago

The PrivateMemorySize64 actually comes from ProcessInfo.PrivateBytes and that is directly extracted from /proc/PID/stat file, the VmData field. I guess that the reason is that actually we consume much less memory on Alpine, so the values are true. I think it may be related to a bug in reading CPU cache size on some distros that was fixed recently in main. See #100502

Baklap4 commented 4 months ago

The PrivateMemorySize64 actually comes from ProcessInfo.PrivateBytes and that is directly extracted from /proc/PID/stat file, the VmData field. I guess that the reason is that actually we consume much less memory on Alpine, so the values are true.

Yes that's the behavior i noticed aswell (that it reads from the proc fs). Alpine is mostly used for its smaller size on disk, not persé its memory footprint although thats usually a nice side effect of having a bare minimum system.

Checking out the results with docker stats gives an average of 40-50mb ram used per container (no matter what distro debian/ubuntu/alpine) so something doesn't add up right i think?

Alpine uses MUSL libc while Debian and Ubuntu use GNU libc, cgroups must behave differently between those two.

@MichalPetryka Hmm that's correct, but it seems PrivateMemorySize64 comes from the proc fs (which isn't directly tied to cgroups right? )

I think it may be related to a bug in reading CPU cache size on some distros that was fixed recently in main. See #100502

Im not that familiar with the details in the linked issue, but what i grasped from it was there were differences for Debian 12 vs 11 and Ubuntu 22 and Ubuntu 21. I see it was recently fixed, but when does this get released into a version? We're currently using dotnet 7. and we're planning to upgrade soon to dotnet 8.

janvorli commented 4 months ago

when does this get released into a version?

It was backported to release/8.0-staging branch and approved, so I believe it should be part of the next .NET 8 release.

jozkee commented 2 months ago

@Baklap4 were you able to verify if your issue was addressed by https://github.com/dotnet/runtime/pull/100502 in 8.0.5?

dotnet-policy-service[bot] commented 2 months ago

This issue has been marked needs-author-action and may be missing some important information.

dotnet-policy-service[bot] commented 1 month ago

This issue has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

dotnet-policy-service[bot] commented 1 month ago

This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.