1 // Created on: 2011-10-05
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #if (defined(_WIN32) || defined(__WIN32__))
23 #pragma comment(lib, "Psapi.lib")
25 #elif (defined(__APPLE__))
26 #include <mach/task.h>
27 #include <mach/mach.h>
28 #include <malloc/malloc.h>
38 #include <OSD_MemInfo.hxx>
40 #if defined(__EMSCRIPTEN__)
41 #include <emscripten.h>
43 //! Return WebAssembly heap size in bytes.
44 EM_JS(size_t, OSD_MemInfo_getModuleHeapLength, (), {
45 return Module.HEAP8.length;
49 // =======================================================================
50 // function : OSD_MemInfo
52 // =======================================================================
53 OSD_MemInfo::OSD_MemInfo (const Standard_Boolean theImmediateUpdate)
55 SetActive (Standard_True);
56 if (theImmediateUpdate)
66 // =======================================================================
67 // function : SetActive
69 // =======================================================================
70 void OSD_MemInfo::SetActive (const Standard_Boolean theActive)
72 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
74 SetActive ((Counter)anIter, theActive);
78 // =======================================================================
81 // =======================================================================
82 void OSD_MemInfo::Clear()
84 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
86 myCounters[anIter] = Standard_Size(-1);
90 // =======================================================================
93 // =======================================================================
94 void OSD_MemInfo::Update()
99 #if (_WIN32_WINNT >= 0x0500)
100 if (IsActive (MemVirtual))
102 MEMORYSTATUSEX aStatEx;
103 aStatEx.dwLength = sizeof(aStatEx);
104 GlobalMemoryStatusEx (&aStatEx);
105 myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual);
108 if (IsActive (MemVirtual))
111 aStat.dwLength = sizeof(aStat);
112 GlobalMemoryStatus (&aStat);
113 myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual);
117 if (IsActive (MemPrivate)
118 || IsActive (MemWorkingSet)
119 || IsActive (MemWorkingSetPeak)
120 || IsActive (MemSwapUsage)
121 || IsActive (MemSwapUsagePeak))
124 HANDLE aProcess = GetCurrentProcess();
125 #if (_WIN32_WINNT >= 0x0501)
126 PROCESS_MEMORY_COUNTERS_EX aProcMemCnts;
128 PROCESS_MEMORY_COUNTERS aProcMemCnts;
130 if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts)))
132 #if (_WIN32_WINNT >= 0x0501)
133 myCounters[MemPrivate] = aProcMemCnts.PrivateUsage;
135 myCounters[MemWorkingSet] = aProcMemCnts.WorkingSetSize;
136 myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize;
137 myCounters[MemSwapUsage] = aProcMemCnts.PagefileUsage;
138 myCounters[MemSwapUsagePeak] = aProcMemCnts.PeakPagefileUsage;
142 if (IsActive (MemHeapUsage))
146 hinfo._pentry = NULL;
148 myCounters[MemHeapUsage] = 0;
149 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
151 if (hinfo._useflag == _USEDENTRY)
153 myCounters[MemHeapUsage] += hinfo._size;
158 #elif defined(__EMSCRIPTEN__)
159 if (IsActive (MemHeapUsage)
160 || IsActive (MemWorkingSet)
161 || IsActive (MemWorkingSetPeak))
163 // /proc/%d/status is not emulated - get more info from mallinfo()
164 const struct mallinfo aMI = mallinfo();
165 if (IsActive (MemHeapUsage))
167 myCounters[MemHeapUsage] = aMI.uordblks;
169 if (IsActive (MemWorkingSet))
171 myCounters[MemWorkingSet] = aMI.uordblks;
173 if (IsActive (MemWorkingSetPeak))
175 myCounters[MemWorkingSetPeak] = aMI.usmblks;
178 if (IsActive (MemVirtual))
180 myCounters[MemVirtual] = OSD_MemInfo_getModuleHeapLength();
182 #elif (defined(__linux__) || defined(__linux))
183 if (IsActive (MemHeapUsage))
185 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
186 #if __GLIBC_PREREQ(2,33)
187 #define HAS_MALLINFO2
192 const struct mallinfo2 aMI = mallinfo2();
194 const struct mallinfo aMI = mallinfo();
196 myCounters[MemHeapUsage] = aMI.uordblks;
199 if (!IsActive (MemVirtual)
200 && !IsActive (MemWorkingSet)
201 && !IsActive (MemWorkingSetPeak)
202 && !IsActive (MemPrivate))
207 // use procfs on Linux
209 snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
212 if (!aFile.is_open())
219 memset (aBuff, 0, sizeof(aBuff));
220 aFile.getline (aBuff, 4096);
221 if (aBuff[0] == '\0')
226 if (IsActive (MemVirtual)
227 && strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0)
229 myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024;
231 //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0)
232 // myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024;
233 else if (IsActive (MemWorkingSet)
234 && strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0)
236 myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size
238 else if (IsActive (MemWorkingSetPeak)
239 && strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0)
241 myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark
243 else if (IsActive (MemPrivate)
244 && strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0)
246 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
247 myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024;
249 else if (IsActive (MemPrivate)
250 && strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0)
252 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
253 myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024;
257 #elif (defined(__APPLE__))
258 if (IsActive (MemVirtual)
259 || IsActive (MemWorkingSet)
260 || IsActive (MemHeapUsage))
262 struct task_basic_info aTaskInfo;
263 mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
264 if (task_info (mach_task_self(), TASK_BASIC_INFO,
265 (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS)
267 // On Mac OS X, these values in bytes, not pages!
268 myCounters[MemVirtual] = aTaskInfo.virtual_size;
269 myCounters[MemWorkingSet] = aTaskInfo.resident_size;
271 //Getting malloc statistics
272 malloc_statistics_t aStats;
273 malloc_zone_statistics (NULL, &aStats);
275 myCounters[MemHeapUsage] = aStats.size_in_use;
282 // =======================================================================
283 // function : ToString
285 // =======================================================================
286 TCollection_AsciiString OSD_MemInfo::ToString() const
288 TCollection_AsciiString anInfo;
289 if (hasValue (MemPrivate))
291 anInfo += TCollection_AsciiString(" Private memory: ") + Standard_Integer (ValueMiB (MemPrivate)) + " MiB\n";
293 if (hasValue (MemWorkingSet))
295 anInfo += TCollection_AsciiString(" Working Set: ") + Standard_Integer (ValueMiB (MemWorkingSet)) + " MiB";
296 if (hasValue (MemWorkingSetPeak))
298 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemWorkingSetPeak)) + " MiB)";
302 if (hasValue (MemSwapUsage))
304 anInfo += TCollection_AsciiString(" Pagefile usage: ") + Standard_Integer (ValueMiB (MemSwapUsage)) + " MiB";
305 if (hasValue (MemSwapUsagePeak))
307 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemSwapUsagePeak)) + " MiB)";
311 if (hasValue (MemVirtual))
313 anInfo += TCollection_AsciiString(" Virtual memory: ") + Standard_Integer (ValueMiB (MemVirtual)) + " MiB\n";
315 if (hasValue (MemHeapUsage))
317 anInfo += TCollection_AsciiString(" Heap memory: ") + Standard_Integer (ValueMiB (MemHeapUsage)) + " MiB\n";
322 // =======================================================================
325 // =======================================================================
326 Standard_Size OSD_MemInfo::Value (const OSD_MemInfo::Counter theCounter) const
328 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
330 return Standard_Size(-1);
332 return myCounters[theCounter];
335 // =======================================================================
336 // function : ValueMiB
338 // =======================================================================
339 Standard_Size OSD_MemInfo::ValueMiB (const OSD_MemInfo::Counter theCounter) const
341 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
343 return Standard_Size(-1);
345 return (myCounters[theCounter] == Standard_Size(-1))
346 ? Standard_Size(-1) : (myCounters[theCounter] / (1024 * 1024));
349 // =======================================================================
350 // function : ValuePreciseMiB
352 // =======================================================================
353 Standard_Real OSD_MemInfo::ValuePreciseMiB (const OSD_MemInfo::Counter theCounter) const
355 if (theCounter < 0 || theCounter >= MemCounter_NB || !IsActive (theCounter))
359 return (myCounters[theCounter] == Standard_Size(-1))
360 ? -1.0 : ((Standard_Real )myCounters[theCounter] / (1024.0 * 1024.0));
363 // =======================================================================
364 // function : ShowInfo
366 // =======================================================================
367 TCollection_AsciiString OSD_MemInfo::PrintInfo()
370 return anInfo.ToString();