Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Fix available memory extraction on Linux #26764

Merged
merged 4 commits into from
Sep 24, 2019

Conversation

janvorli
Copy link
Member

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.

Close #26568

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.
@janvorli janvorli added this to the 5.0 milestone Sep 18, 2019
@janvorli janvorli self-assigned this Sep 18, 2019
@janvorli
Copy link
Member Author

cc: @kevingosse, @Maoni0, @sergiy-k

@jkotas
Copy link
Member

jkotas commented Sep 18, 2019

Do we need a matching change for standalone GC PAL?

@janvorli
Copy link
Member Author

Do we need a matching change for standalone GC PAL?

Yes, we will need it. In fact, I've found that the standalone GC uses a completely different way to get the physical memory used, which is in fact even more incorrect (it is based on memory consumed by the current process instead of the system one). I'll extend this PR with the standalone GC fix.

uint64_t available;
int fieldsParsed = sscanf(line, "MemAvailable: %" SCNu64 " %cB", &available, &units);

if (fieldsParsed >= 1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be >=2 since we need to parse values for 2 fields?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, since the units fields can be missing. So we will either get just the "available" or "available" and "units".

@janvorli janvorli added the * NO MERGE * The PR is not ready for merge yet (see discussion for detailed reasons) label Sep 19, 2019
@janvorli
Copy link
Member Author

I still need to test the standalone GC version, I just needed to push it so that I can fetch the change from my various distros / OS-es. So I am marking it as no merge until I verify that it works as expected on both Linux and OSX.

@Maoni0
Copy link
Member

Maoni0 commented Sep 19, 2019

have you done the perf check with the GC perf infra? @andy-ms added the linux container support

@janvorli
Copy link
Member Author

have you done the perf check with the GC perf infra

Is there any doc on how to do that?

@ghost
Copy link

ghost commented Sep 19, 2019

@janvorli I'll message you on Teams.

The check for whether the memory was restricted or not was incorrect.
static bool ReadMemAvailable(uint64_t* memAvailable)
{
bool foundMemAvailable = false;
FILE* memInfoFile = fopen("/proc/meminfo", "r");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this is fine -- you could also use sysinfo(2) here, which obtains the information from the same place that procfs uses to populate /proc/meminfo, but should work where procfs isn't available for whatever reason.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nevermind, saw it's being used down the line. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we use sysinfo only to extract the swap size. But looking at the sysinfo, it doesn't seem to include the equivalent of the MemAvailable.

return 1;
}

#ifndef __APPLE__

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it better to use platform-specific #ifdefs here? This should be built on FreeBSD as well, where it's going to fail during runtime (and when it's time to add support to other OSes, it's easier to have the preprocessor #error on an #else).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that procfs exists on other Unix systems too. And here we just try once and then fall back to using sysconf, so we don't fail.

@janvorli janvorli removed the * NO MERGE * The PR is not ready for merge yet (see discussion for detailed reasons) label Sep 24, 2019
@janvorli janvorli merged commit 859f464 into dotnet:master Sep 24, 2019
@janvorli janvorli deleted the fix-available-memory-extraction branch September 24, 2019 18:00
wtgodbe pushed a commit that referenced this pull request Oct 14, 2019
* Fix available memory extraction on Linux

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.
MichalStrehovsky pushed a commit to MichalStrehovsky/corert that referenced this pull request Mar 28, 2020
* Fix available memory extraction on Linux

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.

Commit migrated from dotnet/coreclr@859f464
MichalStrehovsky pushed a commit to MichalStrehovsky/corert that referenced this pull request Mar 31, 2020
* Fix available memory extraction on Linux

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.

Commit migrated from dotnet/coreclr@859f464
jkotas pushed a commit to dotnet/corert that referenced this pull request Apr 1, 2020
* Fix available memory extraction on Linux

The GlobalMemoryStatusEx in PAL is returning number of free physical pages in
the ullAvailPhys member. But there are additional pages that are allocated
as buffers and caches that get released when there is a memory pressure and
thus they are effectively available too.

This change extracts the available memory on Linux from the /proc/meminfo
MemAvailable row, which is reported by the kernel as the most precise
amount of available memory.

Commit migrated from dotnet/coreclr@859f464
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GC does not correctly evaluate the memory load on Linux
5 participants