UltraScan III
us_memory.cpp
Go to the documentation of this file.
1 #include "us_memory.h"
3 
4 #ifdef Q_WS_X11
5 #include <sys/sysinfo.h>
6 #include <unistd.h>
7 #endif
8 
9 #ifdef Q_WS_MAC // Mac includes
10 #include <sys/types.h>
11 #include <sys/sysctl.h>
12 #include <mach/mach.h>
13 #include <mach/vm_statistics.h>
14 #include <mach/mach_types.h>
15 #include <mach/mach_init.h>
16 #include <mach/mach_host.h>
17 #endif
18 #ifndef Q_WS_WIN // Unix and Mac includes
19 #include <sys/user.h>
20 #else // Windows includes
21 #include <windows.h>
22 #include <psapi.h>
23 #include <process.h>
24 #endif
25 
26 // Get currently used memory (RSS) in kilobytes
27 long int US_Memory::rss_now( void )
28 {
29  long int rssnow = 0L;
30 
31 #ifdef Q_WS_X11 // Unix: based on /proc/$PID/stat
32  // Read /proc/$pid/stat
33  QFile f( "/proc/" + QString::number( getpid() ) + "/stat" );
34  f.open( QIODevice::ReadOnly );
35  QByteArray ba = f.read( 512 );
36  f.close();
37 
38  const static int kk = PAGE_SIZE / 1024;
39 
40  rssnow = QString( ba ).section( " ", 23, 23 ).toLong() * kk;
41 #endif
42 
43 #ifdef Q_WS_MAC // Mac : use task_info call
44  struct task_basic_info task_stats;
45  mach_msg_type_number_t inf_count = TASK_BASIC_INFO_COUNT;
46  task_t task = current_task();
47 
48  int stat1 = task_info( task, TASK_BASIC_INFO, (task_info_t)&task_stats, &inf_count );
49  if ( stat1 == KERN_SUCCESS )
50  {
51  rssnow = ( (long)task_stats.resident_size + 512 ) / 1024;
52  }
53 #endif
54 
55 #ifdef Q_WS_WIN // Windows: direct use of GetProcessMemoryInfo
56  HANDLE hProcess;
57  DWORD processID;
58  PROCESS_MEMORY_COUNTERS pmc;
59  pmc.cb = (DWORD)sizeof( pmc );
60  processID = _getpid();
61 
62  hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
63  FALSE, processID );
64  if ( hProcess != NULL )
65  {
66  if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof( pmc ) ) )
67  {
68  rssnow = ( (long)pmc.PeakWorkingSetSize + 512 ) / 1024;
69  }
70 
71  CloseHandle( hProcess );
72  }
73 #endif
74 
75  return rssnow;
76 }
77 
78 // Update and return maximum used memory (RSS)
79 long int US_Memory::rss_max( long int& rssmax )
80 {
81  rssmax = qMax( rssmax, rss_now() );
82 
83  return rssmax;
84 }
85 
86 // Return the memory profile: used, available, total
87 int US_Memory::memory_profile( int* pMemA, int* pMemT, int* pMemU )
88 {
89  int memavail;
90  int memtotal;
91  int memused;
92  int memavpc;
93 #ifdef Q_WS_X11 // Unix: use free command
94  QProcess qproc;
95  qproc.start( "free", QStringList() << "-m" );
96  qproc.waitForFinished( -1 );
97  QString totmem = QString( qproc.readAllStandardOutput() ).trimmed();
98  totmem = totmem.section( "\n", 1, 1 );
99  totmem.replace( QRegExp( "\\s+" ), " " );
100 qDebug() << " UsMEM:X11: totmem" << totmem;
101  int fmtotal = totmem.section( " ", 1, 1 ).toInt();
102  int fmused = totmem.section( " ", 2, 2 ).toInt();
103  int fmfree = totmem.section( " ", 3, 3 ).toInt();
104  int fmbuffer = totmem.section( " ", 5, 5 ).toInt();
105  int fmcache = totmem.section( " ", 6, 6 ).toInt();
106 qDebug() << " UsMEM:X11: fmtotal,used,free,buffer,cache" << fmtotal << fmused
107  << fmfree << fmbuffer << fmcache;
108  memtotal = fmtotal;
109  memused = qMax( fmused, ( fmtotal - fmfree - fmcache ) );
110  memavail = memtotal - memused;
111 #endif
112 #ifdef Q_WS_MAC // Mac: use sysctl and rss_now()
113  const double mb_bytes = ( 1024. * 1024. );
114  const double kb_bytes = 1024.;
115  QProcess qproc;
116  qproc.start( "sysctl", QStringList() << "-n" << "hw.memsize" );
117  qproc.waitForFinished( -1 );
118  QString totmem = QString( qproc.readAllStandardOutput() ).trimmed();
119  memtotal = qRound( totmem.toDouble() / mb_bytes );
120  memused = qRound( (double)rss_now() / kb_bytes );
121  memavail = memtotal - memused;
122 qDebug() << " UsMEM:Mac: totmem" << totmem << "memtotal" << memtotal;
123 #endif
124 #ifdef Q_WS_WIN // Windows: direct use of GlobalMemoryStatusEx
125  const double mb_bytes = ( 1024. * 1024. );
126  MEMORYSTATUSEX mstatx;
127  mstatx.dwLength = sizeof( mstatx );
128  GlobalMemoryStatusEx( &mstatx );
129  long memload = (long)mstatx.dwMemoryLoad;
130  memtotal = qRound( (double)mstatx.ullTotalPhys / mb_bytes );
131  memavail = qRound( (double)mstatx.ullAvailPhys / mb_bytes );
132  memused = memtotal - memavail;
133  memavpc = qRound( memavail * 100.0 / memtotal );
134 //qDebug() << " UsMEM:Win: mstatx.dwMemoryLoad" << mstatx.dwMemoryLoad;
135 //qDebug() << " UsMEM:Win: mstatx.ullTotalPhys" << mstatx.ullTotalPhys;
136 //qDebug() << " UsMEM:Win: mstatx.ullAvailPhys" << mstatx.ullAvailPhys;
137 //qDebug() << " UsMEM:Win: gb_bytes" << gb_bytes;
138 qDebug() << " UsMEM:Win: memload" << memload << "memavpc" << memavpc;
139 #endif
140 qDebug() << " UsMEM: memtotal,avail,used" << memtotal << memavail << memused;
141 
142  memavpc = qRound( memavail * 100.0 / memtotal );
143  if ( pMemA != NULL ) *pMemA = memavail;
144  if ( pMemT != NULL ) *pMemT = memtotal;
145  if ( pMemU != NULL ) *pMemU = memused;
146 
147  return memavpc;
148 }
149