https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MemoryUtils.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "MemoryUtils.h"
11#include "MooseError.h"
12
13#include <unistd.h>
14#include <mpi.h>
15#include <fstream>
16#include <array>
17
18#if defined(__APPLE__)
19#include <mach/task.h>
20#include <mach/clock.h>
21#include <mach/mach.h>
22#include <mach/vm_page_size.h>
23#include <sys/types.h>
24#include <sys/sysctl.h>
25#include <sys/vmmeter.h>
26#elif defined(__WIN32__)
27#include <windows.h>
28#include <psapi.h>
29#include <processthreadsapi.h>
30#include <sysinfoapi.h>
31#else
32#include <sys/sysinfo.h>
33#endif
34
35namespace MemoryUtils
36{
37
38std::string
40{
41#ifdef LIBMESH_HAVE_MPI
42 int mpi_namelen;
43 char mpi_name[MPI_MAX_PROCESSOR_NAME];
44 MPI_Get_processor_name(mpi_name, &mpi_namelen);
45 return mpi_name;
46#else
47 return "serial";
48#endif
49}
50
53{
54 return MooseEnum("bytes kibibytes mebibytes gibibytes kilobytes megabytes gigabytes",
55 "mebibytes");
56}
57
58std::size_t
60{
61#if defined(__APPLE__)
62 uint64_t hwmem_size;
63 size_t length = sizeof(hwmem_size);
64 if (0 <= sysctlbyname("hw.memsize", &hwmem_size, &length, NULL, 0))
65 return hwmem_size;
66#elif defined(__WIN32__)
67 ULONGLONG mem_kb;
68 if (GetPhysicallyInstalledSystemMemory(&mem_kb))
69 return mem_kb * 1024;
70#else
71 struct sysinfo si_data;
72 if (!sysinfo(&si_data))
73 return si_data.totalram * si_data.mem_unit;
74#endif
75 return 0;
76}
77
78bool
80{
81 bool retval = false;
82
83 enum StatItem
84 {
85 index_page_faults = 8,
86 index_virtual_size = 19,
87 index_resident_size = 20,
88 num = 21 // total number of entries read
89 };
90
91 // inspect /proc
92 std::ifstream stat_stream("/proc/self/stat", std::ios_base::in);
93 std::array<std::size_t, 21> val;
94 val.fill(0);
95
96 if (stat_stream)
97 {
98 // if the proc filesystem file is found (Linux) read its contents
99 std::string pid, comm, state;
100 stat_stream >> pid >> comm >> state;
101
102 unsigned int i = 0;
103
104 while (!stat_stream.eof() && i < val.size())
105 {
106 stat_stream >> val[i];
107 i++;
108 }
109
110 // Handle the case where we didn't get enough values by just zeroing everything
111 // since we probably got junk
112 if (i != val.size())
113 val.fill(0);
114 else
115 retval = true;
116
117 // resident size is reported as number of pages in /proc
118#ifndef __WIN32__
119 val[index_resident_size] *= sysconf(_SC_PAGE_SIZE);
120#endif
121 }
122 else
123 {
124#ifdef __WIN32__
125 auto pid = GetCurrentProcessId();
126 auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
127
128 PROCESS_MEMORY_COUNTERS pmc;
129 if (NULL == hProcess || !GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
130 val.fill(0);
131 else
132 {
133 retval = true;
134 val[index_page_faults] = pmc.PageFaultCount;
135 val[index_virtual_size] = pmc.WorkingSetSize + pmc.PagefileUsage;
136 val[index_resident_size] = pmc.WorkingSetSize;
137 }
138#else
139 // set all data entries to zero (if all else should fail)
140 val.fill(0);
141#endif
142
143// obtain mach task info on mac OS
144#if defined(__APPLE__)
145 struct task_basic_info t_info;
146 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
147 if (KERN_SUCCESS == task_info(mach_task_self(),
148 TASK_BASIC_INFO,
149 reinterpret_cast<task_info_t>(&t_info),
150 &t_info_count))
151 {
152 retval = true;
153 val[index_virtual_size] = t_info.virtual_size; // in bytes
154 val[index_resident_size] = t_info.resident_size; // in bytes
155 }
156 else
157 mooseDoOnce(::mooseWarning("task_info call failed, memory usage numbers will be incorrect"));
158#endif
159 }
160
161 // physical mem
162 stats._physical_memory = val[index_resident_size];
163
164 // virtual mem
165 stats._virtual_memory = val[index_virtual_size];
166
167 // page faults
168 stats._page_faults = val[index_page_faults];
169
170 return retval;
171}
172
173std::size_t
174convertBytes(std::size_t bytes, MemUnits unit)
175{
176 if (unit == MemUnits::Bytes)
177 return bytes;
178
179 unsigned int nunit = static_cast<unsigned int>(unit);
180
181 // kibi, mebi, gibi
182 if (nunit <= 3)
183 return bytes >> (nunit * 10);
184
185 // kilo, mega, giga
186 if (nunit <= 6)
187 {
188 while (nunit-- > 3)
189 bytes /= 1000;
190 return bytes;
191 }
192
193 mooseError("Unknown memory unit");
194}
195
196} // namespace MemoryUtils
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
std::size_t convertBytes(std::size_t bytes, MemUnits unit)
convert bytes to selected unit prefix
std::string getMPIProcessorName()
get the MPI hostname
Definition MemoryUtils.C:39
bool getMemoryStats(Stats &stats)
get all memory stats for the current process stats The Stats object to fill with the data
Definition MemoryUtils.C:79
std::size_t getTotalRAM()
get the total amount of physical RAM available
Definition MemoryUtils.C:59
MooseEnum getMemUnitsEnum()
get the moose enum for the mem_unit_prefix parameter
Definition MemoryUtils.C:52
std::size_t _virtual_memory
Definition MemoryUtils.h:24
std::size_t _physical_memory
Definition MemoryUtils.h:23
std::size_t _page_faults
Definition MemoryUtils.h:25