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 // =======================================================================
41 // function : OSD_MemInfo
43 // =======================================================================
44 OSD_MemInfo::OSD_MemInfo (const Standard_Boolean theImmediateUpdate)
46 if (theImmediateUpdate)
57 // =======================================================================
60 // =======================================================================
61 void OSD_MemInfo::Clear()
63 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
65 myCounters[anIter] = Standard_Size(-1);
69 // =======================================================================
72 // =======================================================================
73 void OSD_MemInfo::Update()
78 #if (_WIN32_WINNT >= 0x0500)
79 MEMORYSTATUSEX aStatEx;
80 aStatEx.dwLength = sizeof(aStatEx);
81 GlobalMemoryStatusEx (&aStatEx);
82 myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual);
85 aStat.dwLength = sizeof(aStat);
86 GlobalMemoryStatus (&aStat);
87 myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual);
91 HANDLE aProcess = GetCurrentProcess();
92 #if (_WIN32_WINNT >= 0x0501)
93 PROCESS_MEMORY_COUNTERS_EX aProcMemCnts;
95 PROCESS_MEMORY_COUNTERS aProcMemCnts;
97 if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts)))
99 #if (_WIN32_WINNT >= 0x0501)
100 myCounters[MemPrivate] = aProcMemCnts.PrivateUsage;
102 myCounters[MemWorkingSet] = aProcMemCnts.WorkingSetSize;
103 myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize;
104 myCounters[MemSwapUsage] = aProcMemCnts.PagefileUsage;
105 myCounters[MemSwapUsagePeak] = aProcMemCnts.PeakPagefileUsage;
110 hinfo._pentry = NULL;
112 myCounters[MemHeapUsage] = 0;
113 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
115 if(hinfo._useflag == _USEDENTRY)
116 myCounters[MemHeapUsage] += hinfo._size;
119 #elif (defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__))
120 const struct mallinfo aMI = mallinfo();
121 myCounters[MemHeapUsage] = aMI.uordblks;
122 #if defined(__EMSCRIPTEN__)
123 // /proc/%d/status is not emulated - get more info from mallinfo()
124 myCounters[MemWorkingSet] = aMI.uordblks;
125 myCounters[MemWorkingSetPeak] = aMI.usmblks;
128 // use procfs on Linux
130 snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
133 if (!aFile.is_open())
140 memset (aBuff, 0, sizeof(aBuff));
141 aFile.getline (aBuff, 4096);
142 if (aBuff[0] == '\0')
147 if (strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0)
149 myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024;
151 //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0)
152 // myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024;
153 else if (strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0)
155 myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size
157 else if (strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0)
159 myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark
161 else if (strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0)
163 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
164 myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024;
166 else if (strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0)
168 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
169 myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024;
173 #elif (defined(__APPLE__))
174 struct task_basic_info aTaskInfo;
175 mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
176 if (task_info (mach_task_self(), TASK_BASIC_INFO,
177 (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS)
179 // On Mac OS X, these values in bytes, not pages!
180 myCounters[MemVirtual] = aTaskInfo.virtual_size;
181 myCounters[MemWorkingSet] = aTaskInfo.resident_size;
183 //Getting malloc statistics
184 malloc_statistics_t aStats;
185 malloc_zone_statistics (NULL, &aStats);
187 myCounters[MemHeapUsage] = aStats.size_in_use;
193 // =======================================================================
194 // function : ToString
196 // =======================================================================
197 TCollection_AsciiString OSD_MemInfo::ToString() const
199 TCollection_AsciiString anInfo;
200 if (myCounters[MemPrivate] != Standard_Size(-1))
202 anInfo += TCollection_AsciiString(" Private memory: ") + Standard_Integer (ValueMiB (MemPrivate)) + " MiB\n";
204 if (myCounters[MemWorkingSet] != Standard_Size(-1))
206 anInfo += TCollection_AsciiString(" Working Set: ") + Standard_Integer (ValueMiB (MemWorkingSet)) + " MiB";
207 if (myCounters[MemWorkingSetPeak] != Standard_Size(-1))
209 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemWorkingSetPeak)) + " MiB)";
213 if (myCounters[MemSwapUsage] != Standard_Size(-1))
215 anInfo += TCollection_AsciiString(" Pagefile usage: ") + Standard_Integer (ValueMiB (MemSwapUsage)) + " MiB";
216 if (myCounters[MemSwapUsagePeak] != Standard_Size(-1))
218 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemSwapUsagePeak)) + " MiB)";
222 if (myCounters[MemVirtual] != Standard_Size(-1))
224 anInfo += TCollection_AsciiString(" Virtual memory: ") + Standard_Integer (ValueMiB (MemVirtual)) + " MiB\n";
226 if (myCounters[MemHeapUsage] != Standard_Size(-1))
228 anInfo += TCollection_AsciiString(" Heap memory: ") + Standard_Integer (ValueMiB (MemHeapUsage)) + " MiB\n";
233 // =======================================================================
236 // =======================================================================
237 Standard_Size OSD_MemInfo::Value (const OSD_MemInfo::Counter theCounter) const
239 if (theCounter < 0 || theCounter >= MemCounter_NB)
241 return Standard_Size(-1);
243 return myCounters[theCounter];
246 // =======================================================================
247 // function : ValueMiB
249 // =======================================================================
250 Standard_Size OSD_MemInfo::ValueMiB (const OSD_MemInfo::Counter theCounter) const
252 if (theCounter < 0 || theCounter >= MemCounter_NB)
254 return Standard_Size(-1);
256 return (myCounters[theCounter] == Standard_Size(-1))
257 ? Standard_Size(-1) : (myCounters[theCounter] / (1024 * 1024));
260 // =======================================================================
261 // function : ValuePreciseMiB
263 // =======================================================================
264 Standard_Real OSD_MemInfo::ValuePreciseMiB (const OSD_MemInfo::Counter theCounter) const
266 if (theCounter < 0 || theCounter >= MemCounter_NB)
270 return (myCounters[theCounter] == Standard_Size(-1))
271 ? -1.0 : ((Standard_Real )myCounters[theCounter] / (1024.0 * 1024.0));
274 // =======================================================================
275 // function : ShowInfo
277 // =======================================================================
278 TCollection_AsciiString OSD_MemInfo::PrintInfo()
281 return anInfo.ToString();