0031467: Foundation Classes, OSD_MemInfo - disable reading /proc/%d/status with Emscr...
[occt.git] / src / OSD / OSD_MemInfo.cxx
CommitLineData
f0430952 1// Created on: 2011-10-05
2// Created by: Kirill GAVRILOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
f0430952 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
f0430952 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
f0430952 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
f0430952 15
16#if (defined(_WIN32) || defined(__WIN32__))
17 #include <windows.h>
18 #include <winbase.h>
19 #include <process.h>
67a1064e 20 #include <malloc.h>
5fecc495 21 #include <psapi.h>
f0430952 22 #ifdef _MSC_VER
23 #pragma comment(lib, "Psapi.lib")
24 #endif
25#elif (defined(__APPLE__))
26 #include <mach/task.h>
27 #include <mach/mach.h>
67a1064e 28 #include <malloc/malloc.h>
8fa02385 29#else
30 #include <unistd.h>
67a1064e 31 #include <malloc.h>
f0430952 32#endif
33
34#include <string>
35#include <sstream>
36#include <fstream>
37
38#include <OSD_MemInfo.hxx>
39
420f5c86 40#if defined(__EMSCRIPTEN__)
41 #include <emscripten.h>
42
43 //! Return WebAssembly heap size in bytes.
44 EM_JS(size_t, OSD_MemInfo_getModuleHeapLength, (), {
45 return Module.HEAP8.length;
46 });
47#endif
48
f0430952 49// =======================================================================
50// function : OSD_MemInfo
51// purpose :
52// =======================================================================
0be11733 53OSD_MemInfo::OSD_MemInfo (const Standard_Boolean theImmediateUpdate)
f0430952 54{
1939cfd9 55 SetActive (Standard_True);
0be11733 56 if (theImmediateUpdate)
57 {
58 Update();
59 }
60 else
61 {
62 Clear();
63 }
f0430952 64}
65
1939cfd9 66// =======================================================================
67// function : SetActive
68// purpose :
69// =======================================================================
70void OSD_MemInfo::SetActive (const Standard_Boolean theActive)
71{
72 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
73 {
74 SetActive ((Counter)anIter, theActive);
75 }
76}
0be11733 77
f0430952 78// =======================================================================
0be11733 79// function : Clear
f0430952 80// purpose :
81// =======================================================================
0be11733 82void OSD_MemInfo::Clear()
f0430952 83{
f0430952 84 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
85 {
86 myCounters[anIter] = Standard_Size(-1);
87 }
0be11733 88}
89
90// =======================================================================
91// function : Update
92// purpose :
93// =======================================================================
94void OSD_MemInfo::Update()
95{
96 Clear();
742cc8b0 97#ifndef OCCT_UWP
7c65581d 98#if defined(_WIN32)
99#if (_WIN32_WINNT >= 0x0500)
1939cfd9 100 if (IsActive (MemVirtual))
101 {
102 MEMORYSTATUSEX aStatEx;
103 aStatEx.dwLength = sizeof(aStatEx);
104 GlobalMemoryStatusEx (&aStatEx);
105 myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual);
106 }
7c65581d 107#else
1939cfd9 108 if (IsActive (MemVirtual))
109 {
110 MEMORYSTATUS aStat;
111 aStat.dwLength = sizeof(aStat);
112 GlobalMemoryStatus (&aStat);
113 myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual);
114 }
7c65581d 115#endif
f0430952 116
1939cfd9 117 if (IsActive (MemPrivate)
118 || IsActive (MemWorkingSet)
119 || IsActive (MemWorkingSetPeak)
120 || IsActive (MemSwapUsage)
121 || IsActive (MemSwapUsagePeak))
f0430952 122 {
1939cfd9 123 // use Psapi library
124 HANDLE aProcess = GetCurrentProcess();
9fa641d9 125 #if (_WIN32_WINNT >= 0x0501)
1939cfd9 126 PROCESS_MEMORY_COUNTERS_EX aProcMemCnts;
127 #else
128 PROCESS_MEMORY_COUNTERS aProcMemCnts;
9fa641d9 129 #endif
1939cfd9 130 if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts)))
131 {
132 #if (_WIN32_WINNT >= 0x0501)
133 myCounters[MemPrivate] = aProcMemCnts.PrivateUsage;
134 #endif
135 myCounters[MemWorkingSet] = aProcMemCnts.WorkingSetSize;
136 myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize;
137 myCounters[MemSwapUsage] = aProcMemCnts.PagefileUsage;
138 myCounters[MemSwapUsagePeak] = aProcMemCnts.PeakPagefileUsage;
139 }
f0430952 140 }
8fa02385 141
1939cfd9 142 if (IsActive (MemHeapUsage))
67a1064e 143 {
1939cfd9 144 _HEAPINFO hinfo;
145 int heapstatus;
146 hinfo._pentry = NULL;
147
148 myCounters[MemHeapUsage] = 0;
149 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
150 {
151 if (hinfo._useflag == _USEDENTRY)
152 {
153 myCounters[MemHeapUsage] += hinfo._size;
154 }
155 }
67a1064e 156 }
157
420f5c86 158#elif defined(__EMSCRIPTEN__)
159 if (IsActive (MemHeapUsage)
160 || IsActive (MemWorkingSet)
161 || IsActive (MemWorkingSetPeak))
1939cfd9 162 {
420f5c86 163 // /proc/%d/status is not emulated - get more info from mallinfo()
164 const struct mallinfo aMI = mallinfo();
165 if (IsActive (MemHeapUsage))
166 {
167 myCounters[MemHeapUsage] = aMI.uordblks;
168 }
169 if (IsActive (MemWorkingSet))
170 {
171 myCounters[MemWorkingSet] = aMI.uordblks;
172 }
173 if (IsActive (MemWorkingSetPeak))
174 {
175 myCounters[MemWorkingSetPeak] = aMI.usmblks;
176 }
1939cfd9 177 }
420f5c86 178 if (IsActive (MemVirtual))
1939cfd9 179 {
420f5c86 180 myCounters[MemVirtual] = OSD_MemInfo_getModuleHeapLength();
1939cfd9 181 }
420f5c86 182#elif (defined(__linux__) || defined(__linux))
183 if (IsActive (MemHeapUsage))
1939cfd9 184 {
420f5c86 185 const struct mallinfo aMI = mallinfo();
186 myCounters[MemHeapUsage] = aMI.uordblks;
187 }
188
189 if (!IsActive (MemVirtual)
190 && !IsActive (MemWorkingSet)
191 && !IsActive (MemWorkingSetPeak)
192 && !IsActive (MemPrivate))
193 {
194 return;
1939cfd9 195 }
565baee6 196
f0430952 197 // use procfs on Linux
198 char aBuff[4096];
199 snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
200 std::ifstream aFile;
201 aFile.open (aBuff);
202 if (!aFile.is_open())
203 {
204 return;
205 }
206
207 while (!aFile.eof())
208 {
209 memset (aBuff, 0, sizeof(aBuff));
210 aFile.getline (aBuff, 4096);
211 if (aBuff[0] == '\0')
212 {
213 continue;
214 }
215
1939cfd9 216 if (IsActive (MemVirtual)
217 && strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0)
f0430952 218 {
219 myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024;
220 }
221 //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0)
222 // myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024;
1939cfd9 223 else if (IsActive (MemWorkingSet)
224 && strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0)
f0430952 225 {
226 myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size
227 }
1939cfd9 228 else if (IsActive (MemWorkingSetPeak)
229 && strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0)
f0430952 230 {
231 myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark
232 }
1939cfd9 233 else if (IsActive (MemPrivate)
234 && strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0)
f0430952 235 {
236 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
237 myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024;
238 }
1939cfd9 239 else if (IsActive (MemPrivate)
240 && strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0)
f0430952 241 {
242 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
243 myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024;
244 }
245 }
246 aFile.close();
247#elif (defined(__APPLE__))
1939cfd9 248 if (IsActive (MemVirtual)
249 || IsActive (MemWorkingSet)
250 || IsActive (MemHeapUsage))
f0430952 251 {
1939cfd9 252 struct task_basic_info aTaskInfo;
253 mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
254 if (task_info (mach_task_self(), TASK_BASIC_INFO,
255 (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS)
256 {
257 // On Mac OS X, these values in bytes, not pages!
258 myCounters[MemVirtual] = aTaskInfo.virtual_size;
259 myCounters[MemWorkingSet] = aTaskInfo.resident_size;
67a1064e 260
1939cfd9 261 //Getting malloc statistics
262 malloc_statistics_t aStats;
263 malloc_zone_statistics (NULL, &aStats);
67a1064e 264
1939cfd9 265 myCounters[MemHeapUsage] = aStats.size_in_use;
266 }
f0430952 267 }
268#endif
742cc8b0 269#endif
f0430952 270}
271
272// =======================================================================
273// function : ToString
274// purpose :
275// =======================================================================
276TCollection_AsciiString OSD_MemInfo::ToString() const
277{
278 TCollection_AsciiString anInfo;
1939cfd9 279 if (hasValue (MemPrivate))
f0430952 280 {
281 anInfo += TCollection_AsciiString(" Private memory: ") + Standard_Integer (ValueMiB (MemPrivate)) + " MiB\n";
282 }
1939cfd9 283 if (hasValue (MemWorkingSet))
f0430952 284 {
285 anInfo += TCollection_AsciiString(" Working Set: ") + Standard_Integer (ValueMiB (MemWorkingSet)) + " MiB";
1939cfd9 286 if (hasValue (MemWorkingSetPeak))
f0430952 287 {
288 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemWorkingSetPeak)) + " MiB)";
289 }
290 anInfo += "\n";
291 }
1939cfd9 292 if (hasValue (MemSwapUsage))
f0430952 293 {
294 anInfo += TCollection_AsciiString(" Pagefile usage: ") + Standard_Integer (ValueMiB (MemSwapUsage)) + " MiB";
1939cfd9 295 if (hasValue (MemSwapUsagePeak))
f0430952 296 {
297 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemSwapUsagePeak)) + " MiB)";
298 }
299 anInfo += "\n";
300 }
1939cfd9 301 if (hasValue (MemVirtual))
f0430952 302 {
303 anInfo += TCollection_AsciiString(" Virtual memory: ") + Standard_Integer (ValueMiB (MemVirtual)) + " MiB\n";
304 }
1939cfd9 305 if (hasValue (MemHeapUsage))
67a1064e 306 {
307 anInfo += TCollection_AsciiString(" Heap memory: ") + Standard_Integer (ValueMiB (MemHeapUsage)) + " MiB\n";
308 }
f0430952 309 return anInfo;
310}
311
312// =======================================================================
313// function : Value
314// purpose :
315// =======================================================================
316Standard_Size OSD_MemInfo::Value (const OSD_MemInfo::Counter theCounter) const
317{
1939cfd9 318 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
f0430952 319 {
320 return Standard_Size(-1);
321 }
322 return myCounters[theCounter];
323}
324
325// =======================================================================
326// function : ValueMiB
327// purpose :
328// =======================================================================
329Standard_Size OSD_MemInfo::ValueMiB (const OSD_MemInfo::Counter theCounter) const
330{
1939cfd9 331 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
f0430952 332 {
333 return Standard_Size(-1);
334 }
335 return (myCounters[theCounter] == Standard_Size(-1))
336 ? Standard_Size(-1) : (myCounters[theCounter] / (1024 * 1024));
337}
338
0be11733 339// =======================================================================
340// function : ValuePreciseMiB
341// purpose :
342// =======================================================================
343Standard_Real OSD_MemInfo::ValuePreciseMiB (const OSD_MemInfo::Counter theCounter) const
344{
1939cfd9 345 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
0be11733 346 {
347 return -1.0;
348 }
349 return (myCounters[theCounter] == Standard_Size(-1))
350 ? -1.0 : ((Standard_Real )myCounters[theCounter] / (1024.0 * 1024.0));
351}
352
f0430952 353// =======================================================================
354// function : ShowInfo
355// purpose :
356// =======================================================================
357TCollection_AsciiString OSD_MemInfo::PrintInfo()
358{
359 OSD_MemInfo anInfo;
360 return anInfo.ToString();
361}