0030901: Visualization - OSD_MemInfo moving memory computation out of the constructor
[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
40// =======================================================================
41// function : OSD_MemInfo
42// purpose :
43// =======================================================================
0be11733 44OSD_MemInfo::OSD_MemInfo (const Standard_Boolean theImmediateUpdate)
f0430952 45{
0be11733 46 if (theImmediateUpdate)
47 {
48 Update();
49 }
50 else
51 {
52 Clear();
53 }
f0430952 54}
55
0be11733 56
f0430952 57// =======================================================================
0be11733 58// function : Clear
f0430952 59// purpose :
60// =======================================================================
0be11733 61void OSD_MemInfo::Clear()
f0430952 62{
f0430952 63 for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
64 {
65 myCounters[anIter] = Standard_Size(-1);
66 }
0be11733 67}
68
69// =======================================================================
70// function : Update
71// purpose :
72// =======================================================================
73void OSD_MemInfo::Update()
74{
75 Clear();
742cc8b0 76#ifndef OCCT_UWP
7c65581d 77#if defined(_WIN32)
78#if (_WIN32_WINNT >= 0x0500)
f0430952 79 MEMORYSTATUSEX aStatEx;
80 aStatEx.dwLength = sizeof(aStatEx);
81 GlobalMemoryStatusEx (&aStatEx);
82 myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual);
7c65581d 83#else
84 MEMORYSTATUS aStat;
85 aStat.dwLength = sizeof(aStat);
86 GlobalMemoryStatus (&aStat);
87 myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual);
88#endif
f0430952 89
90 // use Psapi library
91 HANDLE aProcess = GetCurrentProcess();
9fa641d9 92#if (_WIN32_WINNT >= 0x0501)
f0430952 93 PROCESS_MEMORY_COUNTERS_EX aProcMemCnts;
9fa641d9 94#else
95 PROCESS_MEMORY_COUNTERS aProcMemCnts;
96#endif
f0430952 97 if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts)))
98 {
9fa641d9 99 #if (_WIN32_WINNT >= 0x0501)
f0430952 100 myCounters[MemPrivate] = aProcMemCnts.PrivateUsage;
9fa641d9 101 #endif
f0430952 102 myCounters[MemWorkingSet] = aProcMemCnts.WorkingSetSize;
103 myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize;
104 myCounters[MemSwapUsage] = aProcMemCnts.PagefileUsage;
105 myCounters[MemSwapUsagePeak] = aProcMemCnts.PeakPagefileUsage;
106 }
8fa02385 107
67a1064e 108 _HEAPINFO hinfo;
109 int heapstatus;
110 hinfo._pentry = NULL;
111
112 myCounters[MemHeapUsage] = 0;
113 while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
114 {
115 if(hinfo._useflag == _USEDENTRY)
116 myCounters[MemHeapUsage] += hinfo._size;
117 }
118
f0430952 119#elif (defined(__linux__) || defined(__linux))
120 // use procfs on Linux
121 char aBuff[4096];
122 snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
123 std::ifstream aFile;
124 aFile.open (aBuff);
125 if (!aFile.is_open())
126 {
127 return;
128 }
129
130 while (!aFile.eof())
131 {
132 memset (aBuff, 0, sizeof(aBuff));
133 aFile.getline (aBuff, 4096);
134 if (aBuff[0] == '\0')
135 {
136 continue;
137 }
138
139 if (strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0)
140 {
141 myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024;
142 }
143 //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0)
144 // myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024;
145 else if (strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0)
146 {
147 myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size
148 }
149 else if (strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0)
150 {
151 myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark
152 }
153 else if (strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0)
154 {
155 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
156 myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024;
157 }
158 else if (strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0)
159 {
160 if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
161 myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024;
162 }
163 }
164 aFile.close();
67a1064e 165
166 struct mallinfo aMI = mallinfo();
167 myCounters[MemHeapUsage] = aMI.uordblks;
168
f0430952 169#elif (defined(__APPLE__))
170 struct task_basic_info aTaskInfo;
171 mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
172 if (task_info (mach_task_self(), TASK_BASIC_INFO,
173 (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS)
174 {
175 // On Mac OS X, these values in bytes, not pages!
176 myCounters[MemVirtual] = aTaskInfo.virtual_size;
177 myCounters[MemWorkingSet] = aTaskInfo.resident_size;
67a1064e 178
179 //Getting malloc statistics
180 malloc_statistics_t aStats;
181 malloc_zone_statistics (NULL, &aStats);
182
183 myCounters[MemHeapUsage] = aStats.size_in_use;
f0430952 184 }
185#endif
742cc8b0 186#endif
f0430952 187}
188
189// =======================================================================
190// function : ToString
191// purpose :
192// =======================================================================
193TCollection_AsciiString OSD_MemInfo::ToString() const
194{
195 TCollection_AsciiString anInfo;
196 if (myCounters[MemPrivate] != Standard_Size(-1))
197 {
198 anInfo += TCollection_AsciiString(" Private memory: ") + Standard_Integer (ValueMiB (MemPrivate)) + " MiB\n";
199 }
200 if (myCounters[MemWorkingSet] != Standard_Size(-1))
201 {
202 anInfo += TCollection_AsciiString(" Working Set: ") + Standard_Integer (ValueMiB (MemWorkingSet)) + " MiB";
203 if (myCounters[MemWorkingSetPeak] != Standard_Size(-1))
204 {
205 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemWorkingSetPeak)) + " MiB)";
206 }
207 anInfo += "\n";
208 }
209 if (myCounters[MemSwapUsage] != Standard_Size(-1))
210 {
211 anInfo += TCollection_AsciiString(" Pagefile usage: ") + Standard_Integer (ValueMiB (MemSwapUsage)) + " MiB";
212 if (myCounters[MemSwapUsagePeak] != Standard_Size(-1))
213 {
214 anInfo += TCollection_AsciiString(" (peak: ") + Standard_Integer (ValueMiB (MemSwapUsagePeak)) + " MiB)";
215 }
216 anInfo += "\n";
217 }
218 if (myCounters[MemVirtual] != Standard_Size(-1))
219 {
220 anInfo += TCollection_AsciiString(" Virtual memory: ") + Standard_Integer (ValueMiB (MemVirtual)) + " MiB\n";
221 }
67a1064e 222 if (myCounters[MemHeapUsage] != Standard_Size(-1))
223 {
224 anInfo += TCollection_AsciiString(" Heap memory: ") + Standard_Integer (ValueMiB (MemHeapUsage)) + " MiB\n";
225 }
f0430952 226 return anInfo;
227}
228
229// =======================================================================
230// function : Value
231// purpose :
232// =======================================================================
233Standard_Size OSD_MemInfo::Value (const OSD_MemInfo::Counter theCounter) const
234{
235 if (theCounter < 0 || theCounter >= MemCounter_NB)
236 {
237 return Standard_Size(-1);
238 }
239 return myCounters[theCounter];
240}
241
242// =======================================================================
243// function : ValueMiB
244// purpose :
245// =======================================================================
246Standard_Size OSD_MemInfo::ValueMiB (const OSD_MemInfo::Counter theCounter) const
247{
248 if (theCounter < 0 || theCounter >= MemCounter_NB)
249 {
250 return Standard_Size(-1);
251 }
252 return (myCounters[theCounter] == Standard_Size(-1))
253 ? Standard_Size(-1) : (myCounters[theCounter] / (1024 * 1024));
254}
255
256// =======================================================================
0be11733 257// function : ValuePreciseMiB
258// purpose :
259// =======================================================================
260Standard_Real OSD_MemInfo::ValuePreciseMiB (const OSD_MemInfo::Counter theCounter) const
261{
262 if (theCounter < 0 || theCounter >= MemCounter_NB)
263 {
264 return -1.0;
265 }
266 return (myCounters[theCounter] == Standard_Size(-1))
267 ? -1.0 : ((Standard_Real )myCounters[theCounter] / (1024.0 * 1024.0));
268}
269
270// =======================================================================
f0430952 271// function : ShowInfo
272// purpose :
273// =======================================================================
274TCollection_AsciiString OSD_MemInfo::PrintInfo()
275{
276 OSD_MemInfo anInfo;
277 return anInfo.ToString();
278}