summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorMaoni Stephens <Maoni0@users.noreply.github.com>2018-03-27 13:04:26 -0700
committerGitHub <noreply@github.com>2018-03-27 13:04:26 -0700
commitef88a92215a8f90fe0bd8b0327c16bb889902105 (patch)
treebc661a38c1c6a58a0157f0d85fd13e3977346424 /src/vm
parentdff4f7181595e9d4a2dd76971a4465cb8db0eb58 (diff)
downloadcoreclr-ef88a92215a8f90fe0bd8b0327c16bb889902105.tar.gz
coreclr-ef88a92215a8f90fe0bd8b0327c16bb889902105.tar.bz2
coreclr-ef88a92215a8f90fe0bd8b0327c16bb889902105.zip
restrict memory limit by taking VM into consideration (#17177)
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/corhost.cpp8
-rw-r--r--src/vm/gcenv.os.cpp86
2 files changed, 74 insertions, 20 deletions
diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp
index 810c45ffd7..c93c2d8ff6 100644
--- a/src/vm/corhost.cpp
+++ b/src/vm/corhost.cpp
@@ -2952,14 +2952,6 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX)
pMSEX->dwLength = sizeof(MEMORYSTATUSEX);
BOOL fRet = GlobalMemoryStatusEx(pMSEX);
_ASSERTE (fRet);
-
-
- // If the machine has more RAM than virtual address limit, let us cap it.
- // Our GC can never use more than virtual address limit.
- if (pMSEX->ullAvailPhys > pMSEX->ullTotalVirtual)
- {
- pMSEX->ullAvailPhys = pMSEX->ullAvailVirtual;
- }
}
// This is the instance that exposes interfaces out to all the other DLLs of the CLR
diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp
index 8d8630ec62..70dc2619dd 100644
--- a/src/vm/gcenv.os.cpp
+++ b/src/vm/gcenv.os.cpp
@@ -409,11 +409,14 @@ size_t GCToOSInterface::GetVirtualMemoryLimit()
return (size_t)memStatus.ullTotalVirtual;
}
-
static size_t g_RestrictedPhysicalMemoryLimit = (size_t)MAX_PTR;
#ifndef FEATURE_PAL
+// For 32-bit processes the virtual address range could be smaller than the amount of physical
+// memory on the machine/in the container, we need to restrict by the VM.
+static bool g_UseRestrictedVirtualMemory = false;
+
typedef BOOL (WINAPI *PGET_PROCESS_MEMORY_INFO)(HANDLE handle, PROCESS_MEMORY_COUNTERS* memCounters, uint32_t cb);
static PGET_PROCESS_MEMORY_INFO GCGetProcessMemoryInfo = 0;
@@ -429,6 +432,8 @@ static size_t GetRestrictedPhysicalMemoryLimit()
return g_RestrictedPhysicalMemoryLimit;
size_t job_physical_memory_limit = (size_t)MAX_PTR;
+ uint64_t total_virtual = 0;
+ uint64_t total_physical = 0;
BOOL in_job_p = FALSE;
HINSTANCE hinstKernel32 = 0;
@@ -487,6 +492,8 @@ static size_t GetRestrictedPhysicalMemoryLimit()
MEMORYSTATUSEX ms;
::GetProcessMemoryLoad(&ms);
+ total_virtual = ms.ullTotalVirtual;
+ total_physical = ms.ullAvailPhys;
// A sanity check in case someone set a larger limit than there is actual physical memory.
job_physical_memory_limit = (size_t) min (job_physical_memory_limit, ms.ullTotalPhys);
@@ -498,7 +505,40 @@ exit:
{
job_physical_memory_limit = 0;
- FreeLibrary(hinstKernel32);
+ if (hinstKernel32 != 0)
+ {
+ FreeLibrary(hinstKernel32);
+ hinstKernel32 = 0;
+ GCGetProcessMemoryInfo = 0;
+ }
+ }
+
+ // Check to see if we are limited by VM.
+ if (total_virtual == 0)
+ {
+ MEMORYSTATUSEX ms;
+ ::GetProcessMemoryLoad(&ms);
+
+ total_virtual = ms.ullTotalVirtual;
+ total_physical = ms.ullTotalPhys;
+ }
+
+ if (job_physical_memory_limit != 0)
+ {
+ total_physical = job_physical_memory_limit;
+ }
+
+ if (total_virtual < total_physical)
+ {
+ if (hinstKernel32 != 0)
+ {
+ // We can also free the lib here - if we are limited by VM we will not be calling
+ // GetProcessMemoryInfo.
+ FreeLibrary(hinstKernel32);
+ GCGetProcessMemoryInfo = 0;
+ }
+ g_UseRestrictedVirtualMemory = true;
+ job_physical_memory_limit = (size_t)total_virtual;
}
VolatileStore(&g_RestrictedPhysicalMemoryLimit, job_physical_memory_limit);
@@ -558,9 +598,12 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available
size_t workingSetSize;
BOOL status = FALSE;
#ifndef FEATURE_PAL
- PROCESS_MEMORY_COUNTERS pmc;
- status = GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
- workingSetSize = pmc.WorkingSetSize;
+ if (!g_UseRestrictedVirtualMemory)
+ {
+ PROCESS_MEMORY_COUNTERS pmc;
+ status = GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
+ workingSetSize = pmc.WorkingSetSize;
+ }
#else
status = PAL_GetWorkingSetSize(&workingSetSize);
#endif
@@ -587,13 +630,32 @@ void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available
MEMORYSTATUSEX ms;
::GetProcessMemoryLoad(&ms);
-
- if (memory_load != NULL)
- *memory_load = ms.dwMemoryLoad;
- if (available_physical != NULL)
- *available_physical = ms.ullAvailPhys;
- if (available_page_file != NULL)
- *available_page_file = ms.ullAvailPageFile;
+
+#ifndef FEATURE_PAL
+ if (g_UseRestrictedVirtualMemory)
+ {
+ _ASSERTE (ms.ullTotalVirtual == restricted_limit);
+ if (memory_load != NULL)
+ *memory_load = (uint32_t)((float)(ms.ullTotalVirtual - ms.ullAvailVirtual) * 100.0 / (float)ms.ullTotalVirtual);
+ if (available_physical != NULL)
+ *available_physical = ms.ullTotalVirtual;
+
+ // Available page file isn't helpful when we are restricted by virtual memory
+ // since the amount of memory we can reserve is less than the amount of
+ // memory we can commit.
+ if (available_page_file != NULL)
+ *available_page_file = 0;
+ }
+ else
+#endif //!FEATURE_PAL
+ {
+ if (memory_load != NULL)
+ *memory_load = ms.dwMemoryLoad;
+ if (available_physical != NULL)
+ *available_physical = ms.ullAvailPhys;
+ if (available_page_file != NULL)
+ *available_page_file = ms.ullAvailPageFile;
+ }
}
// Get a high precision performance counter