https://mooseframework.inl.gov
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 
35 namespace MemoryUtils
36 {
37 
38 std::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 
58 std::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 
78 bool
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 
173 std::size_t
174 convertBytes(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
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
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
std::size_t _physical_memory
Definition: MemoryUtils.h:23
std::size_t _virtual_memory
Definition: MemoryUtils.h:24
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:336
std::size_t _page_faults
Definition: MemoryUtils.h:25
MooseEnum getMemUnitsEnum()
get the moose enum for the mem_unit_prefix parameter
Definition: MemoryUtils.C:52
std::size_t getTotalRAM()
get the total amount of physical RAM available
Definition: MemoryUtils.C:59
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
std::size_t convertBytes(std::size_t bytes, MemUnits unit)
convert bytes to selected unit prefix
Definition: MemoryUtils.C:174