FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
memory_usage.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
10#include <kernel/util/string.hpp>
12#include <kernel/util/os_windows.hpp>
13#include <kernel/util/dist.hpp>
14
15#ifdef __unix__
16#include <sys/types.h>
17#include <sys/time.h>
18#include <sys/resource.h>
19#include <stdio.h>
20#endif
21
22#include <fstream>
23#include <vector>
24#include <string>
25
26namespace FEAT
27{
43 {
44 private:
45 std::size_t _current_physical;
46 std::size_t _peak_physical;
47 std::size_t _current_virtual;
48 std::size_t _peak_virtual;
49 std::size_t _current_swap;
50
51 public:
52 MemoryUsage() :
53 _current_physical(0),
54 _peak_physical(0),
55 _current_virtual(0),
56 _peak_virtual(0),
57 _current_swap(0)
58 {
59 stamp();
60 }
61
63 void stamp()
64 {
65#if defined(__linux)
66 String line;
67 std::ifstream status_file("/proc/self/status");
68 if (!status_file.is_open())
69 XABORTM("could not open /proc/self/status!");
70
71 /* man 5 proc:
72 * /proc/[pid]/status
73 * Provides much of the information in /proc/[pid]/stat and
74 * /proc/[pid]/statm in a format that's easier for humans to parse.
75 * The fields are as follows:
76 * Name: Command run by this process.
77 * State: Current state of the process. One of "R (running)", "S (sleeping)", "D (disk sleep)", "T (stopped)", "T (trac-
78 * ing stop)", "Z (zombie)", or "X (dead)".
79 * Tgid: Thread group ID (i.e., Process ID).
80 * Pid: Thread ID (see gettid(2)).
81 * PPid: PID of parent process.
82 * TracerPid: PID of process tracing this process (0 if not being traced).
83 * Uid, Gid: Real, effective, saved set, and file system UIDs (GIDs).
84 * FDSize: Number of file descriptor slots currently allocated.
85 * Groups: Supplementary group list.
86 *! VmPeak: Peak virtual memory size.
87 *! VmSize: Virtual memory size.
88 * VmLck: Locked memory size (see mlock(3)).
89 *! VmHWM: Peak resident set size ("high water mark").
90 *! VmRSS: Resident set size.
91 * VmData, VmStk, VmExe: Size of data, stack, and text segments.
92 * VmLib: Shared library code size.
93 * VmPTE: Page table entries size (since Linux 2.6.10).
94 * Threads: Number of threads in process containing this thread.
95 * [...]
96 */
97 while (std::getline(status_file, line))
98 {
99 if (line.starts_with("VmRSS"))
100 {
101 std::deque<String> v = line.split_by_whitespaces();
102 XASSERTM(v.back() == "kB", "get_memory_usage: unit mismatch!");
103 v.at(v.size() - 2).parse(_current_physical);
104 _current_physical *= 1024;
105 continue;
106 }
107
108 if (line.starts_with("VmHWM"))
109 {
110 std::deque<String> v = line.split_by_whitespaces();
111 XASSERTM(v.back() == "kB", "get_memory_usage: unit mismatch!");
112 v.at(v.size() - 2).parse(_peak_physical);
113 _peak_physical *= 1024;
114 continue;
115 }
116
117 if (line.starts_with("VmSize"))
118 {
119 std::deque<String> v = line.split_by_whitespaces();
120 XASSERTM(v.back() == "kB", "get_memory_usage: unit mismatch!");
121 v.at(v.size() - 2).parse(_current_virtual);
122 _current_virtual *= 1024;
123 continue;
124 }
125
126 if (line.starts_with("VmPeak"))
127 {
128 std::deque<String> v = line.split_by_whitespaces();
129 XASSERTM(v.back() == "kB", "get_memory_usage: unit mismatch!");
130 v.at(v.size() - 2).parse(_peak_virtual);
131 _peak_virtual *= 1024;
132 continue;
133 }
134
135 if (line.starts_with("VmSwap"))
136 {
137 std::deque<String> v = line.split_by_whitespaces();
138 XASSERTM(v.back() == "kB", "get_memory_usage: unit mismatch!");
139 v.at(v.size() - 2).parse(_current_swap);
140 _current_swap *= 1024;
141 continue;
142 }
143 }
144 status_file.close();
145
146#elif defined(_WIN32)
147
148 unsigned long long work_set_size(0ull), work_set_size_peak(0ull), page_file_usage(0ull), page_file_usage_peak(0ull);
149
150 Windows::query_memory_usage(work_set_size, work_set_size_peak, page_file_usage, page_file_usage_peak);
151
152 _current_physical = std::size_t(work_set_size);
153 _current_virtual = std::size_t(page_file_usage);
154 _peak_physical = std::size_t(work_set_size_peak);
155 _peak_virtual = std::size_t(page_file_usage_peak);
156 _current_swap = std::size_t(0);
157
158#elif defined(__unix__)
159 // see:
160 // https://linux.die.net/man/2/getrusage
161 // https://www.freebsd.org/cgi/man.cgi?query=getrusage
162 struct rusage r_usage;
163 if (0 != getrusage(RUSAGE_SELF, &r_usage))
164 XABORTM("Error in getrusage call!");
165 _peak_physical = (std::size_t)r_usage.ru_maxrss;
166 _peak_virtual = (std::size_t)r_usage.ru_maxrss;
167 _current_physical = (std::size_t)r_usage.ru_maxrss;
168 _current_virtual = (std::size_t)r_usage.ru_maxrss;
169 _current_swap = std::size_t(0);
170 // 'ru_maxrss' is given in kilobytes
171 _peak_physical *= 1024u;
172 _peak_virtual *= 1024u;
173 _current_physical *= 1024u;
174 _current_virtual *= 1024u;
175#endif
176 }
177
179 std::size_t get_current_physical() const
180 {
181 return _current_physical;
182 }
183
185 std::size_t get_peak_physical() const
186 {
187 return _peak_physical;
188 }
189
191 std::size_t get_current_virtual() const
192 {
193 return _current_virtual;
194 }
195
197 std::size_t get_peak_virtual() const
198 {
199 return _peak_virtual;
200 }
201
203 std::size_t get_current_swap() const
204 {
205 return _current_swap;
206 }
207
210 {
211 String r;
212 r += String("Current real:").pad_back(20) + stringify(_current_physical / 1024 / 1024) + " MByte\n";
213 r += String("Peak real:").pad_back(20) + stringify(_peak_physical / 1024 / 1024) + " MByte\n";
214 r += String("Current virtual:").pad_back(20) + stringify(_current_virtual / 1024 / 1024) + " MByte\n";
215 r += String("Peak virtual:").pad_back(20) + stringify(_peak_virtual / 1024 / 1024) + " MByte\n";
216 r += String("Current swap:").pad_back(20) + stringify(_current_swap / 1024 / 1024) + " MByte\n";
217
218 return r;
219 }
220
228 {
229 MemoryUsage mu;
230 std::uint64_t min_p, max_p, sum_p;
231 min_p = max_p = sum_p = mu.get_peak_physical();
232 comm.allreduce(&min_p, &min_p, 1u, Dist::op_min);
233 comm.allreduce(&max_p, &min_p, 1u, Dist::op_max);
234 comm.allreduce(&sum_p, &sum_p, 1u, Dist::op_sum);
235 return stringify_bytes(sum_p, 3, 0) + " [ Max: " + stringify_bytes(max_p, 3, 0) + " / Min: " + stringify_bytes(min_p, 3, 0) + " ]";
236 }
237 }; //class MemoryUsage
238} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
Communicator class.
Definition: dist.hpp:1349
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
Definition: dist.cpp:655
Memory usage info object.
std::size_t get_peak_virtual() const
Returns peak virtual memory.
std::size_t get_current_swap() const
Returns current (last stamp call) swap memory.
std::size_t get_current_physical() const
Returns current (last stamp call) physical memory.
std::size_t get_peak_physical() const
Returns peak physical memory.
void stamp()
update the memory usage statistics with current data
static String format_peak_physical_usage(const Dist::Comm &comm)
Returns the formatted peak physical memory usage over an entire communicator.
std::size_t get_current_virtual() const
Returns current (last stamp call) virtual memory.
String get_formatted_memory_usage() const
Retrieve formatted memory usage string.
String class implementation.
Definition: string.hpp:46
std::deque< String > split_by_whitespaces() const
Splits the string by white-spaces.
Definition: string.hpp:518
String pad_back(size_type len, char c=' ') const
Pads the back of the string up to a desired length.
Definition: string.hpp:415
bool starts_with(const String &head) const
Checks whether this string starts with another string.
Definition: string.hpp:731
const Operation op_min(MPI_MIN)
Operation wrapper for MPI_MIN.
Definition: dist.hpp:275
const Operation op_max(MPI_MAX)
Operation wrapper for MPI_MAX.
Definition: dist.hpp:273
const Operation op_sum(MPI_SUM)
Operation wrapper for MPI_SUM.
Definition: dist.hpp:271
void query_memory_usage(unsigned long long &work_set_size, unsigned long long &work_set_size_peak, unsigned long long &page_file_usage, unsigned long long &page_file_usage_peak)
Queries memory usage information.
Definition: os_windows.cpp:41
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
String stringify_bytes(std::uint64_t bytes, int precision=3, int width=7)
Prints a byte size to a string using the common units Bytes, KiB, MiB, Gib, TiB or PiB.
Definition: string.hpp:1261