dotnet / runtime

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

On macOS `Process.PrivateMemorySize64` returns `0` #105665

Open nwoolls opened 3 months ago

nwoolls commented 3 months ago

Description

Accessing Process.PrivateMemorySize64 on macOS returns 0. This was initially reported, and fixed, for Linux here. Follow-up comments mention macOS but the issue was closed.

The implementation of AssertNonZeroAllZeroDarwin seems to indicate this is acknowledged, if not by-design. But the XML comments for Process.PrivateMemorySize64 doesn't mention any such limitation.

Not sure if this is a bug or feature request, but I'd love to see this implemented for macOS. We're trying to troubleshoot some memory usage but coming up short in our dev environments because of this.

Reproduction Steps

mkdir app-macos-PrivateMemorySize64
cd app-macos-PrivateMemorySize64
dotnet new console
using System.Diagnostics;

var process = Process.GetCurrentProcess();
Console.WriteLine(process.PrivateMemorySize64);
dotnet run

Expected behavior

Outputs "the amount of private memory, in bytes, allocated for the associated process".

Actual behavior

Outputs 0.

Regression?

No

Known Workarounds

None

Configuration

dotnet --version
8.0.303
sw_vers
ProductName:        macOS
ProductVersion:     14.5
BuildVersion:       23F79
uname -a
Darwin nathanialsmbpm2.lan 23.5.0 Darwin Kernel Version 23.5.0: Wed May  1 20:14:38 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6020 arm64

Other information

No response

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

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process See info in area-owners.md if you want to be subscribed.

ShawnWu33 commented 3 weeks ago

Hi, did a bit investigation on this. Apology first if the terminologies are not accurate enough as I am new to this community.

TL;DR

The private memory size of a process is not exposed in macOS (OSX) SDK, hence the value remains default int value as 0;

Investigation details

  1. The Process.PrivateMemorySize64 having a getter function which will first ensure process information being retrieved. https://github.com/dotnet/runtime/blob/112ef3d680c50ae3c64d7c129b658d9cd00a5a3d/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs#L494-L501

  2. When process information did not existed, it trigger ProcessManager to retrieve the process information. https://github.com/dotnet/runtime/blob/112ef3d680c50ae3c64d7c129b658d9cd00a5a3d/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs#L978-L984

  3. The process manager invoke Interop.libproc.GetProcessInfoById(pid) to get process information.https://github.com/dotnet/runtime/blob/112ef3d680c50ae3c64d7c129b658d9cd00a5a3d/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs#L44 Which eventually hitting macOS libproc API proc_pidinfo https://github.com/dotnet/runtime/blob/112ef3d680c50ae3c64d7c129b658d9cd00a5a3d/src/libraries/Common/src/Interop/OSX/Interop.libproc.GetProcessInfoById.cs#L116

  4. Per macOS libproc header file proc_info.h (screenshot attached), the response from that API incldues only virtual memory size and resident memory size. Hence the field PrivateBytes in ProcessInfo is not assigned, remains default value.

    image

Postscript

This issue is known from very first commit of ProcessManager.OSX, It is a comment there mentioning fields didn't being assigned as not available in macOS.

https://github.com/dotnet/runtime/blob/112ef3d680c50ae3c64d7c129b658d9cd00a5a3d/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs#L69-L75

So I don't see a proper fix available at curren time point.