// Get memory status // Parameters: // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { uint64_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { PROCESS_MEMORY_COUNTERS pmc; if (GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { if (memory_load) *memory_load = (uint32_t)((float)pmc.WorkingSetSize * 100.0 / (float)restricted_limit); if (available_physical) *available_physical = restricted_limit - pmc.WorkingSetSize; // Available page file doesn't mean much when physical memory is restricted since // we don't know how much of it is available to this process so we are not going to // bother to make another OS call for it. if (available_page_file) *available_page_file = 0; return; } } MEMORYSTATUSEX ms; ::GetProcessMemoryLoad(&ms); if (memory_load != nullptr) *memory_load = ms.dwMemoryLoad; if (available_physical != nullptr) *available_physical = ms.ullAvailPhys; if (available_page_file != nullptr) *available_page_file = ms.ullAvailPageFile; }
// Get the physical memory that this process can use. // Return: // non zero if it has succeeded, 0 if it has failed // Remarks: // If a process runs with a restricted memory limit, it returns the limit. If there's no limit // specified, it returns amount of actual physical memory. uint64_t GCToOSInterface::GetPhysicalMemoryLimit() { size_t restricted_limit; // The limit was not cached if (g_RestrictedPhysicalMemoryLimit == 0) { restricted_limit = GetRestrictedPhysicalMemoryLimit(); VolatileStore(&g_RestrictedPhysicalMemoryLimit, restricted_limit); } restricted_limit = g_RestrictedPhysicalMemoryLimit; if (restricted_limit != 0 && restricted_limit != SIZE_T_MAX) return restricted_limit; long pages = sysconf(_SC_PHYS_PAGES); if (pages == -1) { return 0; } long pageSize = sysconf(_SC_PAGE_SIZE); if (pageSize == -1) { return 0; } return pages * pageSize; }
// Get the physical memory that this process can use. // Return: // non zero if it has succeeded, 0 if it has failed uint64_t GCToOSInterface::GetPhysicalMemoryLimit() { LIMITED_METHOD_CONTRACT; size_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) return restricted_limit; MEMORYSTATUSEX memStatus; ::GetProcessMemoryLoad(&memStatus); return memStatus.ullTotalPhys; }
// Get the physical memory that this process can use. // Return: // non zero if it has succeeded, 0 if it has failed // Remarks: // If a process runs with a restricted memory limit, it returns the limit. If there's no limit // specified, it returns amount of actual physical memory. uint64_t GCToOSInterface::GetPhysicalMemoryLimit() { size_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) return restricted_limit; MEMORYSTATUSEX memStatus; if (::GlobalMemoryStatusEx(&memStatus)) { return memStatus.ullTotalPhys; } return 0; }
// Get memory status // Parameters: // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. // Remarks: // Any parameter can be null. void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { LIMITED_METHOD_CONTRACT; uint64_t restricted_limit = GetRestrictedPhysicalMemoryLimit(); if (restricted_limit != 0) { size_t workingSetSize; BOOL status = FALSE; #ifndef FEATURE_PAL if (!g_UseRestrictedVirtualMemory) { PROCESS_MEMORY_COUNTERS pmc; status = GCGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); workingSetSize = pmc.WorkingSetSize; } #else status = PAL_GetWorkingSetSize(&workingSetSize); #endif if(status) { if (memory_load) *memory_load = (uint32_t)((float)workingSetSize * 100.0 / (float)restricted_limit); if (available_physical) { if(workingSetSize > restricted_limit) *available_physical = 0; else *available_physical = restricted_limit - workingSetSize; } // Available page file doesn't mean much when physical memory is restricted since // we don't know how much of it is available to this process so we are not going to // bother to make another OS call for it. if (available_page_file) *available_page_file = 0; return; } } MEMORYSTATUSEX ms; ::GetProcessMemoryLoad(&ms); #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; } }