ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
MemoryInfo.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "MemoryInfo.h"
9 
10 #include <CVPlatform.h>
11 
12 #include <cmath>
13 #include <iomanip>
14 
15 #if defined(CV_WINDOWS)
16 #include <windows.h>
17 
18 #include <sstream>
19 #elif defined(CV_LINUX)
20 #include <sys/sysinfo.h>
21 
22 #include <fstream>
23 #include <limits>
24 #elif defined(CV_MAC_OS)
25 #include <mach/host_info.h>
26 #include <mach/mach_host.h>
27 #include <mach/mach_init.h>
28 #include <mach/mach_types.h>
29 #include <mach/vm_statistics.h>
30 #include <sys/sysctl.h>
31 #include <sys/types.h>
32 
33 #include <sstream>
34 #else
35 #warning "System unrecognized. Can't found memory infos."
36 #include <limits>
37 #endif
38 
39 namespace cloudViewer {
40 namespace system {
41 
42 #if defined(CV_LINUX)
43 unsigned long linuxGetAvailableRam() {
44  std::string token;
45  std::ifstream file("/proc/meminfo");
46  while (file >> token) {
47  if (token == "MemAvailable:") {
48  unsigned long mem;
49  if (file >> mem) {
50  // read in kB and convert to bytes
51  return mem * 1024;
52  } else {
53  return 0;
54  }
55  }
56  // ignore rest of the line
57  file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
58  }
59  return 0; // nothing found
60 }
61 #endif
62 
64  MemoryInfo infos;
65 
66 #if defined(CV_WINDOWS)
67  MEMORYSTATUS memory;
68  GlobalMemoryStatus(&memory);
69 
70  // memory.dwMemoryLoad;
71  infos.totalRam = memory.dwTotalPhys;
72  infos.availableRam = infos.freeRam = memory.dwAvailPhys;
73  // memory.dwTotalPageFile;
74  // memory.dwAvailPageFile;
75  infos.totalSwap = memory.dwTotalVirtual;
76  infos.freeSwap = memory.dwAvailVirtual;
77 #elif defined(CV_LINUX)
78  struct sysinfo sys_info;
79  sysinfo(&sys_info);
80 
81  infos.totalRam = sys_info.totalram * sys_info.mem_unit;
82  infos.freeRam = sys_info.freeram * sys_info.mem_unit;
83 
85  if (infos.availableRam == 0) infos.availableRam = infos.freeRam;
86 
87  // infos.sharedRam = sys_info.sharedram * sys_info.mem_unit;
88  // infos.bufferRam = sys_info.bufferram * sys_info.mem_unit;
89  infos.totalSwap = sys_info.totalswap * sys_info.mem_unit;
90  infos.freeSwap = sys_info.freeswap * sys_info.mem_unit;
91 #elif defined(CV_MAC_OS)
92  uint64_t physmem;
93  size_t len = sizeof physmem;
94  int mib[2] = {CTL_HW, HW_MEMSIZE};
95  size_t miblen = sizeof(mib) / sizeof(mib[0]);
96 
97  // Total physical memory.
98  if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 &&
99  len == sizeof(physmem))
100  infos.totalRam = physmem;
101 
102  // Virtual memory.
103  mib[0] = CTL_VM;
104  mib[1] = VM_SWAPUSAGE;
105  struct xsw_usage swap;
106  len = sizeof(struct xsw_usage);
107  if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0) {
108  infos.totalSwap = swap.xsu_total;
109  infos.freeSwap = swap.xsu_avail;
110  }
111 
112  // In use - Reference ParaView/VTK implementation for macOS memory
113  // statistics Use 64-bit API for accurate memory statistics on modern macOS
114  // systems
115  mach_port_t stat_port = mach_host_self();
116  vm_size_t page_size;
117  vm_statistics64_data_t vm_stat;
118  mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
119  if (KERN_SUCCESS == host_page_size(stat_port, &page_size) &&
120  KERN_SUCCESS == host_statistics64(stat_port, HOST_VM_INFO64,
121  (host_info64_t)&vm_stat, &count)) {
122  // Free RAM: completely free memory pages
123  infos.freeRam = (int64_t)vm_stat.free_count * (int64_t)page_size;
124 
125  // Available RAM: ParaView/VTK style calculation for macOS
126  // Based on ParaView's SystemInformation.cxx implementation:
127  // - GetHostMemoryUsed() returns: (active + wired) * page_size
128  // - GetAvailablePhysicalMemory() returns: (free + inactive) * page_size
129  // ParaView status bar uses GetHostMemoryUsed() for memory usage display
130  // So: Used = active + wired, Available = Total - Used
131  uint64_t app_memory = ((uint64_t)vm_stat.active_count +
132  (uint64_t)vm_stat.wire_count) *
133  (uint64_t)page_size;
134  infos.availableRam = infos.totalRam - app_memory;
135  }
136 #else
137  // TODO: could be done on FreeBSD too
138  // see https://github.com/xbmc/xbmc/blob/master/xbmc/linux/XMemUtils.cpp
139  infos.totalRam = infos.freeRam = infos.availableRam = infos.totalSwap =
141 #endif
142 
143  return infos;
144 }
145 
146 std::ostream& operator<<(std::ostream& os, const MemoryInfo& infos) {
147  const double convertionGb = std::pow(2, 30);
148  os << std::setw(5)
149  << "\t- Total RAM: " << (infos.totalRam / convertionGb) << " GB"
150  << std::endl
151  << "\t- Free RAM: " << (infos.freeRam / convertionGb) << " GB"
152  << std::endl
153  << "\t- Available RAM: " << (infos.availableRam / convertionGb) << " GB"
154  << std::endl
155  << "\t- Total swap: " << (infos.totalSwap / convertionGb) << " GB"
156  << std::endl
157  << "\t- Free swap: " << (infos.freeSwap / convertionGb) << " GB"
158  << std::endl;
159  return os;
160 }
161 
162 std::string MemoryInfo::toString() {
163  std::stringstream info;
164  info << *this;
165  return info.str();
166 }
167 
168 } // namespace system
169 } // namespace cloudViewer
int count
#define NULL
int max(int a, int b)
Definition: cutil_math.h:48
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
MemoryInfo getMemoryInfo()
Definition: MemoryInfo.cpp:63
unsigned long linuxGetAvailableRam()
Definition: MemoryInfo.cpp:43
std::ostream & operator<<(std::ostream &os, const MemoryInfo &infos)
Definition: MemoryInfo.cpp:146
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
Definition: Optional.h:890
Generic file read and write utility for python interface.