Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
osutils.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
21#include <ored/version.hpp>
22
23#include <fstream>
24#include <iomanip>
25#include <sstream>
26
27#include <boost/version.hpp>
28#include <ql/version.hpp>
29
30#if defined(_WIN32) || defined(_WIN64)
31#include <intrin.h>
32// windows.h must be included before psapi.h
33// clang-format off
34#include <windows.h>
35#include <psapi.h>
36// clang-format on
37#elif __APPLE__
38#include <sys/sysctl.h>
39#include <unistd.h>
40#include <mach/mach.h>
41#else
42#include <boost/algorithm/string/predicate.hpp>
43#include <boost/algorithm/string/trim.hpp>
44#include <stdio.h>
45#include <sys/resource.h> // getrusage()
46#include <sys/utsname.h> // uname()
47#include <unistd.h>
48#endif
49
50#if defined(_WIN32) || defined(_WIN64)
51#include <boost/version.hpp>
52#if BOOST_VERSION > 106500
53#include <boost/stacktrace.hpp>
54#endif
55#else
56#include <execinfo.h>
57#include <signal.h>
58#endif
59
60using namespace std;
61
62namespace {
63string memoryString(unsigned long long m) {
64 ostringstream oss;
65 oss << fixed << setprecision(2);
66 if (m < 1024)
67 oss << m << "B";
68 else if (m < 1024 * 1024)
69 oss << m / (double)1024 << "kB";
70 else if (m < 1024 * 1024 * 1024)
71 oss << m / (double)(1024 * 1024) << "MB";
72 else
73 oss << m / (double)(1024 * 1024 * 1024) << "GB";
74 return oss.str();
75}
76} // namespace
77
78namespace ore {
79namespace data {
80namespace os {
81
83 ostringstream oss;
84 oss << "System Details:" << endl;
85 oss << " OS : " << os::getOsName() << endl;
86 oss << " OS Version : " << os::getOsVersion() << endl;
87 oss << " CPU : " << os::getCpuName() << endl;
88 oss << " Cores : " << os::getNumberCores() << endl;
89 oss << " Memory (Available) : " << os::getMemoryRAM() << endl;
90 oss << " Memory (Process) : " << os::getMemoryUsage() << endl;
91 oss << " Hostname : " << os::getHostname() << endl;
92 oss << " Username : " << os::getUsername() << endl;
93 oss << " ORE Version : " << OPEN_SOURCE_RISK_VERSION << endl;
94 oss << " QuantLib Version : " << QL_VERSION << endl;
95 oss << " Boost Version : " << BOOST_LIB_VERSION << endl;
96 return oss.str();
97}
98
99string getMemoryUsage() { return memoryString(getMemoryUsageBytes()); }
100
101string getPeakMemoryUsage() { return memoryString(getPeakMemoryUsageBytes()); }
102
103// -------------------------------------
104// ---- Windows stuff
105// -------------------------------------
106#if defined(_WIN32) || defined(_WIN64)
107
108string getOsName() {
109#ifdef _WIN64
110 return "Windows 64-bit";
111#else
112 return "Windows 32-bit";
113#endif
114}
115
116// Ignore "warning C4996: 'GetVersionExA': was declared deprecated"
117#pragma warning(push)
118#pragma warning(disable : 4996)
119string getOsVersion() {
120 OSVERSIONINFO osvi;
121
122 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
123 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
124
125 GetVersionEx(&osvi);
126
127 ostringstream oss;
128 oss << osvi.dwMajorVersion << "." << osvi.dwMinorVersion << "." << osvi.dwBuildNumber << " " << osvi.szCSDVersion;
129 return oss.str();
130
131// Restore "warning C4996: 'GetVersionExA': was declared deprecated" to previous setting
132#pragma warning(pop)
133}
134
135string getCpuName() {
136 int CPUInfo[4] = {-1};
137 char CPUBrandString[0x40];
138 __cpuid(CPUInfo, 0x80000000);
139 int nExIds = CPUInfo[0];
140
141 memset(CPUBrandString, 0, sizeof(CPUBrandString));
142
143 // Get the information associated with each extended ID.
144 for (int i = 0x80000002; i <= nExIds; ++i) {
145 __cpuid(CPUInfo, i);
146 // Interpret CPU brand string.
147 if (i == 0x80000002)
148 memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
149 else if (i == 0x80000003)
150 memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
151 else if (i == 0x80000004)
152 memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
153 }
154 return CPUBrandString;
155}
156
157unsigned int getNumberCores() {
158 SYSTEM_INFO sysinfo;
159 GetSystemInfo(&sysinfo);
160 return sysinfo.dwNumberOfProcessors;
161}
162
163string getMemoryRAM() {
164 unsigned long long mem = 0;
165 if (!GetPhysicallyInstalledSystemMemory(&mem))
166 return "?";
167 return memoryString(mem * 1024);
168}
169
170unsigned long long getMemoryUsageBytes() {
171 PROCESS_MEMORY_COUNTERS info;
172 if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
173 return 0;
174 return info.WorkingSetSize;
175}
176
177unsigned long long getPeakMemoryUsageBytes() {
178 PROCESS_MEMORY_COUNTERS info;
179 if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
180 return 0;
181 return info.PeakWorkingSetSize;
182}
183
184string getUsername() {
185 char acUserName[256 + 1];
186 DWORD nUserName = sizeof(acUserName);
187 if (!GetUserName(acUserName, &nUserName))
188 return "?";
189 acUserName[nUserName] = '\0';
190 return acUserName;
191}
192
193string getHostname() {
194 char buf[MAX_COMPUTERNAME_LENGTH + 1];
195 DWORD buflen = sizeof(buf);
196 if (!GetComputerName(buf, &buflen))
197 return "?";
198 buf[buflen] = '\0';
199 return buf;
200}
201
202// -------------------------------------
203// ---- Generic *nix Stuff
204// -------------------------------------
205#else
206
207unsigned long long getPeakMemoryUsageBytes() {
208 rusage ru;
209 getrusage(RUSAGE_SELF, &ru);
210#if defined __APPLE__
211 return (size_t)ru.ru_maxrss;
212#else
213 return (size_t)(ru.ru_maxrss * 1024L);
214#endif
215}
216
217string getUsername() {
218 char* login = getlogin();
219#ifdef __linux__
220 if (!login)
221 login = cuserid(NULL);
222#endif
223 return login;
224}
225
226string getHostname() {
227 char buf[100];
228 size_t buflen = 100;
229 gethostname(buf, buflen);
230 buf[buflen - 1] = '\0';
231 return buf;
232}
233
234// -------------------------------------
235// ---- Mac OS Stuff
236// -------------------------------------
237#ifdef __APPLE__
238
239string getOsName() { return "Mac OSX"; }
240
241string getOsVersion() {
242 char buf[100];
243 size_t buflen = 100;
244 sysctlbyname("kern.osversion", &buf, &buflen, NULL, 0);
245 return string(buf);
246}
247
248string getCpuName() {
249 char buf[100];
250 size_t buflen = 100;
251 sysctlbyname("machdep.cpu.brand_string", &buf, &buflen, NULL, 0);
252 return string(buf);
253}
254
255unsigned int getNumberCores() {
256 // hw.physicalcpu_max
257 int64_t ncpus;
258 size_t len = sizeof(ncpus);
259 sysctlbyname("hw.physicalcpu_max", &ncpus, &len, NULL, 0);
260 return ncpus;
261}
262
263unsigned long long getMemoryUsageBytes() {
264 struct mach_task_basic_info info;
265 mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
266 if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) != KERN_SUCCESS)
267 return 0ULL; /* Can't access? */
268 return (unsigned long long)info.resident_size;
269}
270
271string getMemoryRAM() {
272 int64_t mem;
273 size_t len = sizeof(mem);
274 sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
275 return memoryString(mem);
276}
277
278// -------------------------------------
279// ---- Linux Stuff
280// -------------------------------------
281
282#else
283
284string getOsName() {
285#if defined(__unix) || defined(__unix__)
286 return "Unix";
287#elif __linux__
288 return "Linux";
289#elif __FreeBSD__
290 return "FreeBSD";
291#else
292 return "Other";
293#endif
294}
295
296string getOsVersion() {
297 struct utsname unameData;
298 if (uname(&unameData))
299 return "?"; // error
300 else
301 return unameData.release;
302}
303
304static string parseProcFile(const char* filename, const string& nodename) {
305 ifstream ifile(filename);
306 if (ifile.is_open()) {
307 string line;
308 while (!ifile.eof()) {
309 getline(ifile, line);
310 if (boost::starts_with(line, nodename)) {
311 string result = line.substr(nodename.size() + 1);
312 boost::trim(result);
313 if (result.size() > 0 && result.at(0) == ':') {
314 // remove leading :
315 result = result.substr(1);
316 boost::trim(result);
317 }
318 ifile.close();
319 return result;
320 }
321 }
322 ifile.close();
323 }
324 return "";
325}
326
327string getCpuName() { return parseProcFile("/proc/cpuinfo", "model name"); }
328
329unsigned int getNumberCores() {
330 long n = sysconf(_SC_NPROCESSORS_ONLN);
331 if (n < 0) // error
332 return 0;
333 else
334 return n;
335}
336
337unsigned long long getMemoryUsageBytes() {
338 unsigned long long rss = 0ULL;
339 FILE* fp = NULL;
340 if ((fp = fopen("/proc/self/statm", "r")) == NULL)
341 return 0ULL; /* Can't open? */
342 if (fscanf(fp, "%*s%llu", &rss) != 1) {
343 fclose(fp);
344 return 0ULL; /* Can't read? */
345 }
346 fclose(fp);
347 return (unsigned long long)rss * (unsigned long long)sysconf(_SC_PAGESIZE);
348}
349
350string getMemoryRAM() { return parseProcFile("/proc/meminfo", "MemTotal"); }
351
352#endif
353
354#endif
355
356// So boost stacktrace is nice, but it needs boost 1.65.1 or higher and it needs linker flags on linux (-rdynamic and
357// -ldl) and one windows we need even more on OSX "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define
358// `_GNU_SOURCE` macro
359//
360// So for now we just use old unix functions backtrace() and backtrace_symbols()
362
363 // we overload st here...
364#if defined(_WIN32) || defined(_WIN64)
365#if BOOST_VERSION > 106500
366 boost::stacktrace::stacktrace st = boost::stacktrace::stacktrace();
367 unsigned st_size = st.size();
368#else
369 char** st = NULL;
370 unsigned st_size = 0;
371#endif
372#else
373 char** st;
374 unsigned st_size = 0;
375 void* callstack[1024];
376 st_size = backtrace(callstack, 1024);
377 st = backtrace_symbols(callstack, st_size);
378#endif
379
380 // Write st_size and st[] to both std::cerr and ALOG
381 std::cerr << "Stacktrace " << st_size << " frames:" << std::endl;
382 ALOG("Stacktrace " << st_size << " frames:")
383 for (unsigned int i = 0; i < st_size; i++) {
384 std::cerr << "#" << i << " " << st[i] << std::endl;
385 ALOG("#" << i << " " << st[i]);
386 }
387
388#if defined(_WIN32) || defined(_WIN64)
389#else
390 if (st)
391 free(st);
392#endif
393}
394
395#if defined(_WIN32) || defined(_WIN64)
396void setAssertHandler() { LOG("oreplus::data::setAssertHandler() not defined for Windows") }
397
398#else // apple and linux
399
400static void _oreplus_handler(int sig) {
401 ALOG("Received Signal " << sig)
403}
404
406 ALOG("Setting ORE+ SigAction handler to intercept SIGABRT signals");
407
408 // Just in case someone calls this twice
409 static bool sigaction_is_set = false;
410 if (!sigaction_is_set) {
411 struct sigaction psa;
412 psa.sa_handler = _oreplus_handler;
413 sigaction(SIGABRT, &psa, NULL);
414 sigaction(SIGSEGV, &psa, NULL);
415 sigaction_is_set = true;
416 }
417}
418#endif
419
420} // end namespace os
421} // end namespace data
422} // end namespace ore
string getPeakMemoryUsage()
Returns the current process peak memory usage.
Definition: osutils.cpp:101
string getCpuName()
Returns the CPU name (e.g. "Intel(R) Core(TM) i7-3720QM CPU @ 2.60GHz".
Definition: osutils.cpp:327
string getMemoryUsage()
Returns the current process memory usage.
Definition: osutils.cpp:99
string getHostname()
Returns the machine name.
Definition: osutils.cpp:226
string getUsername()
Returns the current username.
Definition: osutils.cpp:217
string getOsName()
Returns the OS Name.
Definition: osutils.cpp:284
void setAssertHandler()
Set an assert handler that logs the stacktrace.
Definition: osutils.cpp:405
string getMemoryRAM()
Returns the total amount of memory available (installed RAM)
Definition: osutils.cpp:350
void dumpStacktrace()
Write the current stacktrace to stderr and LOG() with level = ALERT.
Definition: osutils.cpp:361
string getOsVersion()
Returns the OS Version.
Definition: osutils.cpp:296
string getSystemDetails()
Returns all the above system details in a single string.
Definition: osutils.cpp:82
unsigned long long getPeakMemoryUsageBytes()
Returns the current process peak memory usage in bytes.
Definition: osutils.cpp:207
unsigned long long getMemoryUsageBytes()
Definition: osutils.cpp:337
unsigned int getNumberCores()
Returns the number of Cores available to the OS.
Definition: osutils.cpp:329
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Various OS specific utilities.
ORE version as defined in QuantExt.
#define OPEN_SOURCE_RISK_VERSION