9#include "MantidKernel/DllConfig.h"
18#include <sys/resource.h>
23#include <mach/mach_host.h>
25#include <malloc/malloc.h>
26#include <sys/sysctl.h>
39Logger
g_log(
"Memory");
44 std::stringstream buffer;
45 if (mem_in_kiB <
static_cast<TYPE>(1024))
46 buffer << mem_in_kiB <<
" kB";
47 else if (mem_in_kiB <
static_cast<TYPE>(100 * 1024 * 1024))
48 buffer << (mem_in_kiB /
static_cast<TYPE>(1024)) <<
" MB";
50 buffer << (mem_in_kiB /
static_cast<TYPE>(1024 * 1024)) <<
" GB";
73 ifstream stat_stream(
"/proc/self/stat", ios_base::in);
76 string pid, comm, state, ppid, pgrp, session, tty_nr;
77 string tpgid, flags, minflt, cminflt, majflt, cmajflt;
78 string utime, stime, cutime, cstime, priority, nice;
79 string O, itrealvalue, starttime;
85 stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >> minflt >> cminflt >>
86 majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >> nice >> O >> itrealvalue >> starttime >>
89 long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024;
90 vm_usage =
static_cast<size_t>(vsize /
static_cast<long double>(1024.0));
91 resident_set =
static_cast<size_t>(rss * page_size_kb);
96 struct task_basic_info t_info;
97 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
100 task_info(mach_task_self(), TASK_BASIC_INFO,
reinterpret_cast<task_info_t
>(&t_info), &t_info_count)) {
105 mach_port_t port = mach_host_self();
106 host_page_size(port, &pageSize);
107 resident_set =
static_cast<size_t>(t_info.resident_size * pageSize);
108 vm_usage =
static_cast<size_t>(t_info.virtual_size * pageSize / 1024L);
112 DWORD pid = GetCurrentProcessId();
113 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
114 if (NULL == hProcess)
116 PROCESS_MEMORY_COUNTERS pmc;
117 if (GetProcessMemoryInfo(hProcess, &pmc,
sizeof(pmc))) {
118 vm_usage = pmc.PagefileUsage / 1024;
119 resident_set = pmc.WorkingSetSize / 1024;
121 CloseHandle(hProcess);
136bool read_mem_info(
size_t &sys_avail,
size_t &sys_total) {
137 std::ifstream file(
"/proc/meminfo");
142 while (getline(file, line)) {
143 std::istringstream is(line);
149 if (tag ==
"MemTotal:") {
152 }
else if (tag ==
"MemFree:") {
155 }
else if (tag ==
"Cached:") {
158 }
else if (tag ==
"Buffers:") {
163 if (values_found == 4) {
205 if (!read_mem_info(sys_avail, sys_total)) {
206 long int totPages = sysconf(_SC_PHYS_PAGES);
207 long int avPages = sysconf(_SC_AVPHYS_PAGES);
208 long int pageSize = sysconf(_SC_PAGESIZE);
218 sys_avail = totPages / 1024 * pageSize;
222#ifdef __GLIBC_MINOR__
223#if __GLIBC_MINOR__ >= 33
224 auto info = mallinfo2();
226 auto info = mallinfo();
229 auto info = mallinfo();
232 const size_t unusedReserved = info.fordblks / 1024;
233 g_log.
debug() <<
"Linux - Adding reserved but unused memory of " << unusedReserved <<
" KB\n";
234 sys_avail += unusedReserved;
239 size_t len =
sizeof(totalmem);
241 int err = sysctlbyname(
"hw.memsize", &totalmem, &len,
nullptr, 0);
244 sys_total = totalmem / 1024;
246 mach_port_t port = mach_host_self();
249 host_page_size(port, &pageSize);
252 vm_statistics vmStats;
253 mach_msg_type_number_t
count;
254 count =
sizeof(vm_statistics) /
sizeof(natural_t);
255 err = host_statistics(port, HOST_VM_INFO,
reinterpret_cast<host_info_t
>(&vmStats), &
count);
257 g_log.
warning(
"Unable to obtain memory statistics for this Mac.");
258 sys_avail = pageSize * (vmStats.free_count + vmStats.inactive_count) / 1024;
261 const size_t unusedReserved = mstats().bytes_free / 1024;
262 g_log.
debug() <<
"Mac - Adding reserved but unused memory of " << unusedReserved <<
" KB\n";
263 sys_avail += unusedReserved;
265 GlobalMemoryStatusEx(&memStatus);
266 if (memStatus.ullTotalPhys < memStatus.ullTotalVirtual) {
267 sys_avail =
static_cast<size_t>(memStatus.ullAvailPhys / 1024);
268 sys_total =
static_cast<size_t>(memStatus.ullTotalPhys / 1024);
272 sys_avail =
static_cast<size_t>(memStatus.ullAvailVirtual / 1024);
273 sys_total =
static_cast<size_t>(memStatus.ullTotalVirtual / 1024);
277 g_log.
debug() <<
"Memory: " << sys_avail <<
" (free), " << sys_total <<
" (total).\n";
289 static bool initialized(
false);
308 mallopt(M_MMAP_THRESHOLD, 8 * 4096);
310 Logger memOptLogger(
"MemoryOptions");
316 const DWORD numHeap = GetProcessHeaps(1024, hHeaps);
317 memOptLogger.
debug() <<
"Number of heaps: " << numHeap <<
"\n";
318 ULONG ulEnableLFH = 2;
319 for (DWORD i = 0; i < numHeap; i++) {
320 if (!HeapSetInformation(hHeaps[i], HeapCompatibilityInformation, &ulEnableLFH,
sizeof(ulEnableLFH))) {
321 memOptLogger.
debug() <<
"Failed to enable the LFH for heap " << i <<
"\n";
337 memStatus.dwLength =
sizeof(MEMORYSTATUSEX);
433 MEMORY_BASIC_INFORMATION info;
435 size_t unusedReserved = 0;
437 GlobalMemoryStatusEx(&memStatus);
438 DWORDLONG GB2 = memStatus.ullTotalVirtual;
442 VirtualQuery(addr, &info,
sizeof(MEMORY_BASIC_INFORMATION));
445 if (info.State == MEM_RESERVE)
446 unusedReserved += info.RegionSize;
448 addr += info.RegionSize;
449 size += info.RegionSize;
450 }
while (size < GB2);
453 unusedReserved /= 1024;
455 return unusedReserved;
472 out <<
"virtual[" << stats.
vmUsageStr() <<
"] ";
476 out <<
"available[" << stats.
availMemStr() <<
"] ";
493 PROCESS_MEMORY_COUNTERS info;
494 GetProcessMemoryInfo(GetCurrentProcess(), &info,
sizeof(info));
495 return (
size_t)info.PeakWorkingSetSize;
497#elif (defined(_AIX) || defined(__TOS__AIX__)) || \
498 (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
500 struct psinfo psinfo;
502 if ((fd = open(
"/proc/self/psinfo", O_RDONLY)) == -1)
504 if (read(fd, &psinfo,
sizeof(psinfo)) !=
sizeof(psinfo)) {
509 return (
size_t)(psinfo.pr_rssize * 1024L);
511#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
513 struct rusage rusage;
514 getrusage(RUSAGE_SELF, &rusage);
515#if defined(__APPLE__) && defined(__MACH__)
516 return static_cast<size_t>(rusage.ru_maxrss);
518 return (
size_t)(rusage.ru_maxrss * 1024L);
537 PROCESS_MEMORY_COUNTERS info;
538 GetProcessMemoryInfo(GetCurrentProcess(), &info,
sizeof(info));
539 return (
size_t)info.WorkingSetSize;
541#elif defined(__APPLE__) && defined(__MACH__)
543 struct mach_task_basic_info info;
544 mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
545 if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
reinterpret_cast<task_info_t
>(&info), &infoCount) !=
547 return static_cast<size_t>(0L);
548 return static_cast<size_t>(info.resident_size);
550#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
554 if ((fp = fopen(
"/proc/self/statm",
"r")) ==
nullptr)
556 if (fscanf(fp,
"%*s%20ld", &rss) != 1) {
561 return (
size_t)rss * (size_t)sysconf(_SC_PAGESIZE);
577 std::string errorString;
578 const auto availableMemory = this->
availMem() * 1024;
579 if (requestedMemoryBytes > availableMemory) {
580 double constexpr bytesToGB = 1e9;
581 double requestedGB =
static_cast<double>(requestedMemoryBytes) / bytesToGB;
582 double availableGB =
static_cast<double>(availableMemory) / bytesToGB;
583 errorString =
"Requested " +
std::to_string(requestedGB) +
" GB of memory, but only " +
596 return ConfigService::Instance().getValue<
bool>(
"algorithms.memorycheck").value_or(
true);
double value
The value of the point.
The Logger class is in charge of the publishing messages from the framework through various channels.
void debug(const std::string &msg)
Logs at debug level.
void warning(const std::string &msg)
Logs at warning level.
This class is responsible for memory statistics.
std::size_t avail_memory
Available memory of system in kiB.
std::string resUsageStr() const
Returns the resident memory used by the current process.
std::string checkAvailableMemory(std::size_t const requestedMemoryBytes) const
Check if there is enough space in memory to hold the requested amount of memory.
std::string availMemStr() const
Returns the available memory of the system as a string.
static std::mutex mutexMemory
Mutex to avoid simultaneous access to memory resources.
double getFreeRatio() const
The ratio of available to total system memory as a number between 0-100.
std::string vmUsageStr() const
Returns the virtual memory usage as a string.
std::size_t reservedMem() const
Returns the reserved memory that has not been factored into the available memory calculation.
static bool memoryCheckEnabled()
Whether checkAvailableMemory compares a request against the available memory at all.
void ignoreFields(const MemoryStatsIgnore)
Set the fields to ignore.
void update()
Update the structure with current information, taking into account what is to be ignored.
std::size_t res_usage
Resident memory usage by process in kiB.
std::size_t getCurrentRSS() const
MemoryStatsIgnore ignore
What fields to ignore.
std::size_t getPeakRSS() const
std::size_t vm_usage
Virtual memory usage by process in kiB.
std::size_t totalMem() const
Returns the total memory of the system.
MemoryStats(const MemoryStatsIgnore ignore=MEMORY_STATS_IGNORE_NONE)
Constructor.
std::string totalMemStr() const
Returns the total memory of the system as a string.
std::size_t availMem() const
Returns the available memory of the system in kiB.
std::size_t residentMem() const
Returns the memory usage of the current process in kiB.
void process_mem_system(size_t &sys_avail, size_t &sys_total)
Attempts to read the system memory statistics.
std::size_t total_memory
Total physical memory of system in kiB.
std::size_t virtualMem() const
Returns the virtual memory usage of the current process in kiB.
Logger g_log("DateAndTime")
MANTID_KERNEL_DLL void initAllocatorOptions()
Initialize platform-dependent options for memory management.
template MANTID_KERNEL_DLL string memToString< uint64_t >(const uint64_t)
MANTID_KERNEL_DLL std::ostream & operator<<(std::ostream &, CPUTimer &)
Convenience function to provide for easier debug printing.
void process_mem_usage(size_t &vm_usage, size_t &resident_set)
Attempts to read the system-dependent data for a process' virtual memory size and resident set size,...
MemoryStatsIgnore
Enmuerate the ignored memory fields.
@ MEMORY_STATS_IGNORE_SYSTEM
@ MEMORY_STATS_IGNORE_PROCESS
template MANTID_KERNEL_DLL string memToString< uint32_t >(const uint32_t)
std::string memToString(const TYPE mem_in_kiB)
Convert a (number) for memory in kiB to a string with proper units.
std::string to_string(const wide_integer< Bits, Signed > &n)