0027350: Support for Universal Windows Platform
[occt.git] / src / OSD / OSD_MemInfo.cxx
1 // Created on: 2011-10-05
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if (defined(_WIN32) || defined(__WIN32__))
17   #include <windows.h>
18   #include <winbase.h>
19   #include <process.h>
20   #include <malloc.h>
21   #include <Psapi.h>
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>
28   #include <malloc/malloc.h>
29 #else
30   #include <unistd.h>
31   #include <malloc.h>
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 // =======================================================================
44 OSD_MemInfo::OSD_MemInfo()
45 {
46   Update();
47 }
48
49 // =======================================================================
50 // function : Update
51 // purpose  :
52 // =======================================================================
53 void OSD_MemInfo::Update()
54 {
55   // reset values
56   for (Standard_Integer anIter = 0; anIter < MemCounter_NB; ++anIter)
57   {
58     myCounters[anIter] = Standard_Size(-1);
59   }
60 #ifndef OCCT_UWP
61 #if defined(_WIN32)
62 #if (_WIN32_WINNT >= 0x0500)
63   MEMORYSTATUSEX aStatEx;
64   aStatEx.dwLength = sizeof(aStatEx);
65   GlobalMemoryStatusEx (&aStatEx);
66   myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual);
67 #else
68   MEMORYSTATUS aStat;
69   aStat.dwLength = sizeof(aStat);
70   GlobalMemoryStatus (&aStat);
71   myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual);
72 #endif
73
74   // use Psapi library
75   HANDLE aProcess = GetCurrentProcess();
76 #if (_WIN32_WINNT >= 0x0501)
77   PROCESS_MEMORY_COUNTERS_EX aProcMemCnts;
78 #else
79   PROCESS_MEMORY_COUNTERS    aProcMemCnts;
80 #endif
81   if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts)))
82   {
83   #if (_WIN32_WINNT >= 0x0501)
84     myCounters[MemPrivate]        = aProcMemCnts.PrivateUsage;
85   #endif
86     myCounters[MemWorkingSet]     = aProcMemCnts.WorkingSetSize;
87     myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize;
88     myCounters[MemSwapUsage]      = aProcMemCnts.PagefileUsage;
89     myCounters[MemSwapUsagePeak]  = aProcMemCnts.PeakPagefileUsage;
90   }
91
92   _HEAPINFO hinfo;
93   int heapstatus;
94   hinfo._pentry = NULL;
95
96   myCounters[MemHeapUsage] = 0;
97   while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
98   {
99     if(hinfo._useflag == _USEDENTRY)
100       myCounters[MemHeapUsage] += hinfo._size;
101   }
102
103 #elif (defined(__linux__) || defined(__linux))
104   // use procfs on Linux
105   char aBuff[4096];
106   snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
107   std::ifstream aFile;
108   aFile.open (aBuff);
109   if (!aFile.is_open())
110   {
111     return;
112   }
113
114   while (!aFile.eof())
115   {
116     memset (aBuff, 0, sizeof(aBuff));
117     aFile.getline (aBuff, 4096);
118     if (aBuff[0] == '\0')
119     {
120       continue;
121     }
122
123     if (strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0)
124     {
125       myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024;
126     }
127     //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0)
128     //  myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024;
129     else if (strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0)
130     {
131       myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size
132     }
133     else if (strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0)
134     {
135       myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark
136     }
137     else if (strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0)
138     {
139       if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
140       myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024;
141     }
142     else if (strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0)
143     {
144       if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate];
145       myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024;
146     }
147   }
148   aFile.close();
149
150   struct mallinfo aMI = mallinfo();
151   myCounters[MemHeapUsage] = aMI.uordblks;
152
153 #elif (defined(__APPLE__))
154   struct task_basic_info aTaskInfo;
155   mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
156   if (task_info (mach_task_self(), TASK_BASIC_INFO,
157                  (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS)
158   {
159     // On Mac OS X, these values in bytes, not pages!
160     myCounters[MemVirtual]    = aTaskInfo.virtual_size;
161     myCounters[MemWorkingSet] = aTaskInfo.resident_size;
162
163     //Getting malloc statistics
164     malloc_statistics_t aStats;
165     malloc_zone_statistics (NULL, &aStats);
166
167     myCounters[MemHeapUsage] = aStats.size_in_use;
168   }
169 #endif
170 #endif
171 }
172
173 // =======================================================================
174 // function : ToString
175 // purpose  :
176 // =======================================================================
177 TCollection_AsciiString OSD_MemInfo::ToString() const
178 {
179   TCollection_AsciiString anInfo;
180   if (myCounters[MemPrivate] != Standard_Size(-1))
181   {
182     anInfo += TCollection_AsciiString("  Private memory:     ") + Standard_Integer (ValueMiB (MemPrivate)) + " MiB\n";
183   }
184   if (myCounters[MemWorkingSet] != Standard_Size(-1))
185   {
186     anInfo += TCollection_AsciiString("  Working Set:        ") +  Standard_Integer (ValueMiB (MemWorkingSet)) + " MiB";
187     if (myCounters[MemWorkingSetPeak] != Standard_Size(-1))
188     {
189       anInfo += TCollection_AsciiString(" (peak: ") +  Standard_Integer (ValueMiB (MemWorkingSetPeak)) + " MiB)";
190     }
191     anInfo += "\n";
192   }
193   if (myCounters[MemSwapUsage] != Standard_Size(-1))
194   {
195     anInfo += TCollection_AsciiString("  Pagefile usage:     ") +  Standard_Integer (ValueMiB (MemSwapUsage)) + " MiB";
196     if (myCounters[MemSwapUsagePeak] != Standard_Size(-1))
197     {
198       anInfo += TCollection_AsciiString(" (peak: ") +  Standard_Integer (ValueMiB (MemSwapUsagePeak)) + " MiB)";
199     }
200     anInfo += "\n";
201   }
202   if (myCounters[MemVirtual] != Standard_Size(-1))
203   {
204     anInfo += TCollection_AsciiString("  Virtual memory:     ") +  Standard_Integer (ValueMiB (MemVirtual)) + " MiB\n";
205   }
206   if (myCounters[MemHeapUsage] != Standard_Size(-1))
207   {
208     anInfo += TCollection_AsciiString("  Heap memory:     ") +  Standard_Integer (ValueMiB (MemHeapUsage)) + " MiB\n";
209   }
210   return anInfo;
211 }
212
213 // =======================================================================
214 // function : Value
215 // purpose  :
216 // =======================================================================
217 Standard_Size OSD_MemInfo::Value (const OSD_MemInfo::Counter theCounter) const
218 {
219   if (theCounter < 0 || theCounter >= MemCounter_NB)
220   {
221     return Standard_Size(-1);
222   }
223   return myCounters[theCounter];
224 }
225
226 // =======================================================================
227 // function : ValueMiB
228 // purpose  :
229 // =======================================================================
230 Standard_Size OSD_MemInfo::ValueMiB (const OSD_MemInfo::Counter theCounter) const
231 {
232   if (theCounter < 0 || theCounter >= MemCounter_NB)
233   {
234     return Standard_Size(-1);
235   }
236   return (myCounters[theCounter] == Standard_Size(-1))
237        ? Standard_Size(-1) : (myCounters[theCounter] / (1024 * 1024));
238 }
239
240 // =======================================================================
241 // function : ShowInfo
242 // purpose  :
243 // =======================================================================
244 TCollection_AsciiString OSD_MemInfo::PrintInfo()
245 {
246   OSD_MemInfo anInfo;
247   return anInfo.ToString();
248 }