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 |
53 | OSD_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 | // ======================================================================= |
70 | void 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 |
82 | void 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 | // ======================================================================= |
94 | void 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 | // ======================================================================= |
276 | TCollection_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 | // ======================================================================= |
316 | Standard_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 | // ======================================================================= |
329 | Standard_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 | // ======================================================================= |
343 | Standard_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 | // ======================================================================= |
357 | TCollection_AsciiString OSD_MemInfo::PrintInfo() |
358 | { |
359 | OSD_MemInfo anInfo; |
360 | return anInfo.ToString(); |
361 | } |