VirtualBox

source: vbox/trunk/src/VBox/Main/linux/PerformanceLinux.cpp@ 26163

Last change on this file since 26163 was 12546, checked in by vboxsync, 16 years ago

PerfAPI: Improved Linux collector

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.1 KB
Line 
1/* $Id: PerformanceLinux.cpp 12546 2008-09-17 17:11:15Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Linux-specific Performance Classes implementation.
6 */
7
8/*
9 * Copyright (C) 2008 Sun Microsystems, Inc.
10 *
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.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include <stdio.h>
25#include <iprt/alloc.h>
26#include <iprt/err.h>
27#include <iprt/param.h>
28#include <iprt/string.h>
29
30#include <map>
31#include <vector>
32
33#include "Logging.h"
34#include "Performance.h"
35
36namespace pm {
37
38class CollectorLinux : public CollectorHAL
39{
40public:
41 virtual int preCollect(const CollectorHints& hints);
42 virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
43 virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
44
45 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
46 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
47private:
48 virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
49 int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed);
50
51 struct VMProcessStats
52 {
53 uint64_t cpuUser;
54 uint64_t cpuKernel;
55 ULONG pagesUsed;
56 };
57
58 typedef std::map<RTPROCESS, VMProcessStats> VMProcessMap;
59
60 VMProcessMap mProcessStats;
61 uint64_t mUser, mKernel, mIdle;
62};
63
64CollectorHAL *createHAL()
65{
66 return new CollectorLinux();
67}
68
69// Collector HAL for Linux
70
71int CollectorLinux::preCollect(const CollectorHints& hints)
72{
73 std::vector<RTPROCESS> processes;
74 hints.getProcesses(processes);
75
76 std::vector<RTPROCESS>::iterator it;
77 for(it = processes.begin(); it != processes.end(); it++)
78 {
79 VMProcessStats vmStats;
80 int rc = getRawProcessStats(*it, &vmStats.cpuUser, &vmStats.cpuKernel, &vmStats.pagesUsed);
81 if (RT_FAILURE(rc))
82 return rc;
83 mProcessStats[*it] = vmStats;
84 }
85 if (hints.isHostCpuLoadCollected() || mProcessStats.size())
86 {
87 _getRawHostCpuLoad(&mUser, &mKernel, &mIdle);
88 }
89 return VINF_SUCCESS;
90}
91
92int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
93{
94 int rc = VINF_SUCCESS;
95 ULONG u32user, u32nice, u32kernel, u32idle;
96 FILE *f = fopen("/proc/stat", "r");
97
98 if (f)
99 {
100 if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4)
101 {
102 *user = (uint64_t)u32user + u32nice;
103 *kernel = u32kernel;
104 *idle = u32idle;
105 }
106 else
107 rc = VERR_FILE_IO_ERROR;
108 fclose(f);
109 }
110 else
111 rc = VERR_ACCESS_DENIED;
112
113 return rc;
114}
115
116int CollectorLinux::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
117{
118 *user = mUser;
119 *kernel = mKernel;
120 *idle = mIdle;
121 return VINF_SUCCESS;
122}
123
124int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
125{
126 VMProcessMap::const_iterator it = mProcessStats.find(process);
127
128 if (it == mProcessStats.end())
129 {
130 Log (("No stats pre-collected for process %x\n", process));
131 return VERR_INTERNAL_ERROR;
132 }
133 *user = it->second.cpuUser;
134 *kernel = it->second.cpuKernel;
135 *total = mUser + mKernel + mIdle;
136 return VINF_SUCCESS;
137}
138
139int CollectorLinux::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available)
140{
141 int rc = VINF_SUCCESS;
142 ULONG buffers, cached;
143 FILE *f = fopen("/proc/meminfo", "r");
144
145 if (f)
146 {
147 int processed = fscanf(f, "MemTotal: %u kB\n", total);
148 processed += fscanf(f, "MemFree: %u kB\n", available);
149 processed += fscanf(f, "Buffers: %u kB\n", &buffers);
150 processed += fscanf(f, "Cached: %u kB\n", &cached);
151 if (processed == 4)
152 {
153 *available += buffers + cached;
154 *used = *total - *available;
155 }
156 else
157 rc = VERR_FILE_IO_ERROR;
158 fclose(f);
159 }
160 else
161 rc = VERR_ACCESS_DENIED;
162
163 return rc;
164}
165
166int CollectorLinux::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
167{
168 VMProcessMap::const_iterator it = mProcessStats.find(process);
169
170 if (it == mProcessStats.end())
171 {
172 Log (("No stats pre-collected for process %x\n", process));
173 return VERR_INTERNAL_ERROR;
174 }
175 *used = it->second.pagesUsed * (PAGE_SIZE / 1024);
176 return VINF_SUCCESS;
177}
178
179int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed)
180{
181 int rc = VINF_SUCCESS;
182 char *pszName;
183 pid_t pid2;
184 char c;
185 int iTmp;
186 long long unsigned int u64Tmp;
187 unsigned uTmp;
188 unsigned long ulTmp;
189 ULONG u32user, u32kernel;
190 char buf[80]; /* @todo: this should be tied to max allowed proc name. */
191
192 RTStrAPrintf(&pszName, "/proc/%d/stat", process);
193 //printf("Opening %s...\n", pszName);
194 FILE *f = fopen(pszName, "r");
195 RTMemFree(pszName);
196
197 if (f)
198 {
199 if (fscanf(f, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %u %u "
200 "%ld %ld %ld %ld %ld %ld %llu %lu %u",
201 &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
202 &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel,
203 &ulTmp, &ulTmp, &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u64Tmp,
204 &ulTmp, memPagesUsed) == 24)
205 {
206 Assert((pid_t)process == pid2);
207 *cpuUser = u32user;
208 *cpuKernel = u32kernel;
209 }
210 else
211 rc = VERR_FILE_IO_ERROR;
212 fclose(f);
213 }
214 else
215 rc = VERR_ACCESS_DENIED;
216
217 return rc;
218}
219
220}
221
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette