1
/* $Id: PerformanceLinux.cpp 33992 2010-11-11 13:57:03Z vboxsync $ */
5
* VBox Linux-specific Performance Classes implementation.
9
* Copyright (C) 2008 Oracle Corporation
11
* This file is part of VirtualBox Open Source Edition (OSE), as
12
* available from http://www.virtualbox.org. This file is free software;
13
* you can redistribute it and/or modify it under the terms of the GNU
14
* General Public License (GPL) as published by the Free Software
15
* Foundation, in version 2 as it comes in the "COPYING" file of the
16
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
21
#include <iprt/alloc.h>
23
#include <iprt/param.h>
24
#include <iprt/string.h>
30
#include "Performance.h"
34
class CollectorLinux : public CollectorHAL
37
virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */);
38
virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
39
virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
41
virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
42
virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
44
virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
45
int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed);
54
typedef std::map<RTPROCESS, VMProcessStats> VMProcessMap;
56
VMProcessMap mProcessStats;
57
uint64_t mUser, mKernel, mIdle;
60
CollectorHAL *createHAL()
62
return new CollectorLinux();
65
// Collector HAL for Linux
67
int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */)
69
std::vector<RTPROCESS> processes;
70
hints.getProcesses(processes);
72
std::vector<RTPROCESS>::iterator it;
73
for (it = processes.begin(); it != processes.end(); it++)
75
VMProcessStats vmStats;
76
int rc = getRawProcessStats(*it, &vmStats.cpuUser, &vmStats.cpuKernel, &vmStats.pagesUsed);
79
mProcessStats[*it] = vmStats;
81
if (hints.isHostCpuLoadCollected() || mProcessStats.size())
83
_getRawHostCpuLoad(&mUser, &mKernel, &mIdle);
88
int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
90
int rc = VINF_SUCCESS;
91
ULONG u32user, u32nice, u32kernel, u32idle;
92
FILE *f = fopen("/proc/stat", "r");
96
if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4)
98
*user = (uint64_t)u32user + u32nice;
103
rc = VERR_FILE_IO_ERROR;
107
rc = VERR_ACCESS_DENIED;
112
int CollectorLinux::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
120
int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
122
VMProcessMap::const_iterator it = mProcessStats.find(process);
124
if (it == mProcessStats.end())
126
Log (("No stats pre-collected for process %x\n", process));
127
return VERR_INTERNAL_ERROR;
129
*user = it->second.cpuUser;
130
*kernel = it->second.cpuKernel;
131
*total = mUser + mKernel + mIdle;
135
int CollectorLinux::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available)
137
int rc = VINF_SUCCESS;
138
ULONG buffers, cached;
139
FILE *f = fopen("/proc/meminfo", "r");
143
int processed = fscanf(f, "MemTotal: %u kB\n", total);
144
processed += fscanf(f, "MemFree: %u kB\n", available);
145
processed += fscanf(f, "Buffers: %u kB\n", &buffers);
146
processed += fscanf(f, "Cached: %u kB\n", &cached);
149
*available += buffers + cached;
150
*used = *total - *available;
153
rc = VERR_FILE_IO_ERROR;
157
rc = VERR_ACCESS_DENIED;
162
int CollectorLinux::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
164
VMProcessMap::const_iterator it = mProcessStats.find(process);
166
if (it == mProcessStats.end())
168
Log (("No stats pre-collected for process %x\n", process));
169
return VERR_INTERNAL_ERROR;
171
*used = it->second.pagesUsed * (PAGE_SIZE / 1024);
175
int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed)
177
int rc = VINF_SUCCESS;
182
long long unsigned int u64Tmp;
186
ULONG u32user, u32kernel;
187
char buf[80]; /* @todo: this should be tied to max allowed proc name. */
189
RTStrAPrintf(&pszName, "/proc/%d/stat", process);
190
//printf("Opening %s...\n", pszName);
191
FILE *f = fopen(pszName, "r");
196
if (fscanf(f, "%d %79s %c %d %d %d %d %d %u %lu %lu %lu %lu %u %u "
197
"%ld %ld %ld %ld %ld %ld %llu %lu %u",
198
&pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
199
&ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel,
200
&ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &u64Tmp,
201
&ulTmp, memPagesUsed) == 24)
203
Assert((pid_t)process == pid2);
205
*cpuKernel = u32kernel;
208
rc = VERR_FILE_IO_ERROR;
212
rc = VERR_ACCESS_DENIED;