16#include <sys/resource.h>
21#include <mach/mach_host.h>
23#include <malloc/malloc.h>
24#include <sys/sysctl.h>
37Logger
g_log(
"Memory");
42 std::stringstream buffer;
43 if (mem_in_kiB <
static_cast<TYPE>(1024))
44 buffer << mem_in_kiB <<
" kB";
45 else if (mem_in_kiB <
static_cast<TYPE>(100 * 1024 * 1024))
46 buffer << (mem_in_kiB /
static_cast<TYPE>(1024)) <<
" MB";
48 buffer << (mem_in_kiB /
static_cast<TYPE>(1024 * 1024)) <<
" GB";
71 ifstream stat_stream(
"/proc/self/stat", ios_base::in);
74 string pid, comm, state, ppid, pgrp, session, tty_nr;
75 string tpgid, flags, minflt, cminflt, majflt, cmajflt;
76 string utime, stime, cutime, cstime, priority, nice;
77 string O, itrealvalue, starttime;
83 stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >> minflt >> cminflt >>
84 majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >> nice >> O >> itrealvalue >> starttime >>
87 long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024;
88 vm_usage =
static_cast<size_t>(vsize /
static_cast<long double>(1024.0));
89 resident_set =
static_cast<size_t>(rss * page_size_kb);
94 struct task_basic_info t_info;
95 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
98 task_info(mach_task_self(), TASK_BASIC_INFO,
reinterpret_cast<task_info_t
>(&t_info), &t_info_count)) {
103 mach_port_t port = mach_host_self();
104 host_page_size(port, &pageSize);
105 resident_set =
static_cast<size_t>(t_info.resident_size * pageSize);
106 vm_usage =
static_cast<size_t>(t_info.virtual_size * pageSize / 1024L);
110 DWORD pid = GetCurrentProcessId();
111 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
112 if (NULL == hProcess)
114 PROCESS_MEMORY_COUNTERS pmc;
115 if (GetProcessMemoryInfo(hProcess, &pmc,
sizeof(pmc))) {
116 vm_usage = pmc.PagefileUsage / 1024;
117 resident_set = pmc.WorkingSetSize / 1024;
119 CloseHandle(hProcess);
134bool read_mem_info(
size_t &sys_avail,
size_t &sys_total) {
135 std::ifstream file(
"/proc/meminfo");
140 while (getline(file, line)) {
141 std::istringstream is(line);
147 if (tag ==
"MemTotal:") {
150 }
else if (tag ==
"MemFree:") {
153 }
else if (tag ==
"Cached:") {
156 }
else if (tag ==
"Buffers:") {
161 if (values_found == 4) {
203 if (!read_mem_info(sys_avail, sys_total)) {
204 long int totPages = sysconf(_SC_PHYS_PAGES);
205 long int avPages = sysconf(_SC_AVPHYS_PAGES);
206 long int pageSize = sysconf(_SC_PAGESIZE);
216 sys_avail = totPages / 1024 * pageSize;
220#ifdef __GLIBC_MINOR__
221#if __GLIBC_MINOR__ >= 33
222 auto info = mallinfo2();
224 auto info = mallinfo();
227 auto info = mallinfo();
230 const size_t unusedReserved = info.fordblks / 1024;
231 g_log.
debug() <<
"Linux - Adding reserved but unused memory of " << unusedReserved <<
" KB\n";
232 sys_avail += unusedReserved;
237 size_t len =
sizeof(totalmem);
239 int err = sysctlbyname(
"hw.memsize", &totalmem, &len,
nullptr, 0);
242 sys_total = totalmem / 1024;
244 mach_port_t port = mach_host_self();
247 host_page_size(port, &pageSize);
250 vm_statistics vmStats;
251 mach_msg_type_number_t
count;
252 count =
sizeof(vm_statistics) /
sizeof(natural_t);
253 err = host_statistics(port, HOST_VM_INFO,
reinterpret_cast<host_info_t
>(&vmStats), &
count);
255 g_log.
warning(
"Unable to obtain memory statistics for this Mac.");
256 sys_avail = pageSize * (vmStats.free_count + vmStats.inactive_count) / 1024;
259 const size_t unusedReserved = mstats().bytes_free / 1024;
260 g_log.
debug() <<
"Mac - Adding reserved but unused memory of " << unusedReserved <<
" KB\n";
261 sys_avail += unusedReserved;
263 GlobalMemoryStatusEx(&memStatus);
264 if (memStatus.ullTotalPhys < memStatus.ullTotalVirtual) {
265 sys_avail =
static_cast<size_t>(memStatus.ullAvailPhys / 1024);
266 sys_total =
static_cast<size_t>(memStatus.ullTotalPhys / 1024);
270 sys_avail =
static_cast<size_t>(memStatus.ullAvailVirtual / 1024);
271 sys_total =
static_cast<size_t>(memStatus.ullTotalVirtual / 1024);
275 g_log.
debug() <<
"Memory: " << sys_avail <<
" (free), " << sys_total <<
" (total).\n";
287 static bool initialized(
false);
306 mallopt(M_MMAP_THRESHOLD, 8 * 4096);
308 Logger memOptLogger(
"MemoryOptions");
314 const DWORD numHeap = GetProcessHeaps(1024, hHeaps);
315 memOptLogger.
debug() <<
"Number of heaps: " << numHeap <<
"\n";
316 ULONG ulEnableLFH = 2;
317 for (DWORD i = 0; i < numHeap; i++) {
318 if (!HeapSetInformation(hHeaps[i], HeapCompatibilityInformation, &ulEnableLFH,
sizeof(ulEnableLFH))) {
319 memOptLogger.
debug() <<
"Failed to enable the LFH for heap " << i <<
"\n";
335 memStatus.dwLength =
sizeof(MEMORYSTATUSEX);
431 MEMORY_BASIC_INFORMATION info;
433 size_t unusedReserved = 0;
435 GlobalMemoryStatusEx(&memStatus);
436 DWORDLONG GB2 = memStatus.ullTotalVirtual;
440 VirtualQuery(addr, &info,
sizeof(MEMORY_BASIC_INFORMATION));
443 if (info.State == MEM_RESERVE)
444 unusedReserved += info.RegionSize;
446 addr += info.RegionSize;
447 size += info.RegionSize;
448 }
while (size < GB2);
451 unusedReserved /= 1024;
453 return unusedReserved;
470 out <<
"virtual[" << stats.
vmUsageStr() <<
"] ";
474 out <<
"available[" << stats.
availMemStr() <<
"] ";
491 PROCESS_MEMORY_COUNTERS info;
492 GetProcessMemoryInfo(GetCurrentProcess(), &info,
sizeof(info));
493 return (
size_t)info.PeakWorkingSetSize;
495#elif (defined(_AIX) || defined(__TOS__AIX__)) || \
496 (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
498 struct psinfo psinfo;
500 if ((fd = open(
"/proc/self/psinfo", O_RDONLY)) == -1)
502 if (read(fd, &psinfo,
sizeof(psinfo)) !=
sizeof(psinfo)) {
507 return (
size_t)(psinfo.pr_rssize * 1024L);
509#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
511 struct rusage rusage;
512 getrusage(RUSAGE_SELF, &rusage);
513#if defined(__APPLE__) && defined(__MACH__)
514 return static_cast<size_t>(rusage.ru_maxrss);
516 return (
size_t)(rusage.ru_maxrss * 1024L);
535 PROCESS_MEMORY_COUNTERS info;
536 GetProcessMemoryInfo(GetCurrentProcess(), &info,
sizeof(info));
537 return (
size_t)info.WorkingSetSize;
539#elif defined(__APPLE__) && defined(__MACH__)
541 struct mach_task_basic_info info;
542 mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
543 if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
reinterpret_cast<task_info_t
>(&info), &infoCount) !=
545 return static_cast<size_t>(0L);
546 return static_cast<size_t>(info.resident_size);
548#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
552 if ((fp = fopen(
"/proc/self/statm",
"r")) ==
nullptr)
554 if (fscanf(fp,
"%*s%20ld", &rss) != 1) {
559 return (
size_t)rss * (size_t)sysconf(_SC_PAGESIZE);
double value
The value of the point.
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
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 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.
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 DLLExport string memToString< uint32_t >(const uint32_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,...
template DLLExport string memToString< uint64_t >(const uint64_t)
MemoryStatsIgnore
Enmuerate the ignored memory fields.
@ MEMORY_STATS_IGNORE_SYSTEM
@ MEMORY_STATS_IGNORE_PROCESS
std::string memToString(const TYPE mem_in_kiB)
Convert a (number) for memory in kiB to a string with proper units.