VirtualBox

source: vbox/trunk/src/VBox/Main/Performance.cpp@ 10692

Last change on this file since 10692 was 10679, checked in by vboxsync, 17 years ago

Filtering sketched. There is a crash in VirtualBox::uninit on Windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1/* $Id: Performance.cpp 10679 2008-07-15 18:59:56Z vboxsync $ */
2
3/** @file
4 *
5 * VBox 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 <VBox/com/array.h>
25#include <VBox/com/ptr.h>
26#include <VBox/com/string.h>
27#include <VBox/err.h>
28#include <iprt/string.h>
29#include <iprt/mem.h>
30
31#include "Performance.h"
32
33using namespace pm;
34
35// Default factory
36
37BaseMetric *MetricFactory::createHostCpuLoad(IUnknown *object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
38{
39 Assert(mHAL);
40 return new HostCpuLoad(mHAL, object, user, kernel, idle);
41}
42BaseMetric *MetricFactory::createHostCpuMHz(IUnknown *object, SubMetric *mhz)
43{
44 Assert(mHAL);
45 return new HostCpuMhz(mHAL, object, mhz);
46}
47BaseMetric *MetricFactory::createHostRamUsage(IUnknown *object, SubMetric *total, SubMetric *used, SubMetric *available)
48{
49 Assert(mHAL);
50 return new HostRamUsage(mHAL, object, total, used, available);
51}
52BaseMetric *MetricFactory::createMachineCpuLoad(IUnknown *object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
53{
54 Assert(mHAL);
55 return new MachineCpuLoad(mHAL, object, process, user, kernel);
56}
57BaseMetric *MetricFactory::createMachineRamUsage(IUnknown *object, RTPROCESS process, SubMetric *used)
58{
59 Assert(mHAL);
60 return new MachineRamUsage(mHAL, object, process, used);
61}
62
63// Linux factory
64
65MetricFactoryLinux::MetricFactoryLinux()
66{
67 mHAL = new CollectorLinux();
68 Assert(mHAL);
69}
70
71BaseMetric *MetricFactoryLinux::createHostCpuLoad(IUnknown *object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
72{
73 Assert(mHAL);
74 return new HostCpuLoadRaw(mHAL, object, user, kernel, idle);
75}
76
77BaseMetric *MetricFactoryLinux::createMachineCpuLoad(IUnknown *object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
78{
79 Assert(mHAL);
80 return new MachineCpuLoadRaw(mHAL, object, process, user, kernel);
81}
82
83
84// Stubs for non-pure virtual methods
85
86int CollectorHAL::getHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle)
87{
88 return E_NOTIMPL;
89}
90
91int CollectorHAL::getProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel)
92{
93 return E_NOTIMPL;
94}
95
96int CollectorHAL::getRawHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle)
97{
98 return E_NOTIMPL;
99}
100
101int CollectorHAL::getRawProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel)
102{
103 return E_NOTIMPL;
104}
105
106// Collector HAL for Linux
107#include <stdio.h>
108
109int CollectorLinux::getRawHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle)
110{
111#ifdef RT_OS_LINUX
112 int rc = VINF_SUCCESS;
113 unsigned long nice;
114 FILE *f = fopen("/proc/stat", "r");
115
116 if (f)
117 {
118 if (fscanf(f, "cpu %lu %lu %lu %lu", user, &nice, kernel, idle) == 4)
119 *user += nice;
120 else
121 rc = VERR_FILE_IO_ERROR;
122 fclose(f);
123 }
124 else
125 rc = VERR_ACCESS_DENIED;
126
127 return rc;
128#else
129 return E_NOTIMPL;
130#endif
131}
132
133int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel)
134{
135#ifdef RT_OS_LINUX
136 int rc = VINF_SUCCESS;
137 char *pszName;
138 pid_t pid2;
139 char c;
140 int iTmp;
141 unsigned uTmp;
142 unsigned long ulTmp;
143 char buf[80]; /* @todo: this should be tied to max allowed proc name. */
144
145 RTStrAPrintf(&pszName, "/proc/%d/stat", process);
146 //printf("Opening %s...\n", pszName);
147 FILE *f = fopen(pszName, "r");
148 RTMemFree(pszName);
149
150 if (f)
151 {
152 if (fscanf(f, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu",
153 &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
154 &ulTmp, &ulTmp, &ulTmp, &ulTmp, user, kernel) == 15)
155 {
156 Assert((pid_t)process == pid2);
157 }
158 else
159 rc = VERR_FILE_IO_ERROR;
160 fclose(f);
161 }
162 else
163 rc = VERR_ACCESS_DENIED;
164
165 return rc;
166#else
167 return E_NOTIMPL;
168#endif
169}
170
171int CollectorLinux::getHostCpuMHz(unsigned long *mhz)
172{
173 return E_NOTIMPL;
174}
175int CollectorLinux::getHostMemoryUsage(unsigned long *total, unsigned long *used, unsigned long *available)
176{
177 return E_NOTIMPL;
178}
179int CollectorLinux::getProcessMemoryUsage(RTPROCESS process, unsigned long *used)
180{
181 return E_NOTIMPL;
182}
183
184void HostCpuLoad::init(unsigned long period, unsigned long length)
185{
186 mPeriod = period;
187 mLength = length;
188 mUser->init(mLength);
189 mKernel->init(mLength);
190 mIdle->init(mLength);
191}
192
193void HostCpuLoad::collect()
194{
195 unsigned long user, kernel, idle;
196 mHAL->getHostCpuLoad(&user, &kernel, &idle);
197 mUser->put(user);
198 mKernel->put(kernel);
199 mIdle->put(idle);
200}
201
202void HostCpuLoadRaw::collect()
203{
204 unsigned long user, kernel, idle;
205 unsigned long userDiff, kernelDiff, idleDiff, totalDiff;
206
207 mHAL->getRawHostCpuLoad(&user, &kernel, &idle);
208
209 userDiff = user - mUserPrev;
210 kernelDiff = kernel - mKernelPrev;
211 idleDiff = idle - mIdlePrev;
212 totalDiff = userDiff + kernelDiff + idleDiff;
213
214 mUser->put(PM_CPU_LOAD_MULTIPLIER * userDiff / totalDiff);
215 mKernel->put(PM_CPU_LOAD_MULTIPLIER * kernelDiff / totalDiff);
216 mIdle->put(PM_CPU_LOAD_MULTIPLIER * idleDiff / totalDiff);
217
218 mUserPrev = user;
219 mKernelPrev = kernel;
220 mIdlePrev = idle;
221}
222
223void HostCpuMhz::init(unsigned long period, unsigned long length)
224{
225 mPeriod = period;
226 mLength = length;
227 mMHz->init(mLength);
228}
229
230void HostCpuMhz::collect()
231{
232 unsigned long mhz;
233 mHAL->getHostCpuMHz(&mhz);
234 mMHz->put(mhz);
235}
236
237void HostRamUsage::init(unsigned long period, unsigned long length)
238{
239 mPeriod = period;
240 mLength = length;
241 mTotal->init(mLength);
242 mUsed->init(mLength);
243 mAvailable->init(mLength);
244}
245
246void HostRamUsage::collect()
247{
248 unsigned long total, used, available;
249 mHAL->getHostMemoryUsage(&total, &used, &available);
250 mTotal->put(total);
251 mUsed->put(used);
252 mAvailable->put(available);
253}
254
255
256
257void MachineCpuLoad::init(unsigned long period, unsigned long length)
258{
259 mPeriod = period;
260 mLength = length;
261 mUser->init(mLength);
262 mKernel->init(mLength);
263}
264
265void MachineCpuLoad::collect()
266{
267 unsigned long user, kernel;
268 mHAL->getProcessCpuLoad(mProcess, &user, &kernel);
269 mUser->put(user);
270 mKernel->put(kernel);
271}
272
273void MachineCpuLoadRaw::collect()
274{
275 unsigned long hostUser, hostKernel, hostIdle, hostTotal;
276 unsigned long processUser, processKernel;
277
278 mHAL->getRawHostCpuLoad(&hostUser, &hostKernel, &hostIdle);
279 hostTotal = hostUser + hostKernel + hostIdle;
280
281 mHAL->getRawProcessCpuLoad(mProcess, &processUser, &processKernel);
282 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processUser - mProcessUserPrev) / (hostTotal - mHostTotalPrev));
283 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processKernel - mProcessKernelPrev ) / (hostTotal - mHostTotalPrev));
284
285 mHostTotalPrev = hostTotal;
286 mProcessUserPrev = processUser;
287 mProcessKernelPrev = processKernel;
288}
289
290void MachineRamUsage::init(unsigned long period, unsigned long length)
291{
292 mPeriod = period;
293 mLength = length;
294 mUsed->init(mLength);
295}
296
297void MachineRamUsage::collect()
298{
299 unsigned long used;
300 mHAL->getProcessMemoryUsage(mProcess, &used);
301 mUsed->put(used);
302}
303
304void CircularBuffer::init(unsigned long length)
305{
306 if (mData)
307 RTMemFree(mData);
308 mLength = length;
309 mData = (unsigned long *)RTMemAllocZ(length * sizeof(unsigned long));
310 mPosition = 0;
311}
312
313unsigned long CircularBuffer::length()
314{
315 return mLength;
316}
317
318void CircularBuffer::put(unsigned long value)
319{
320 mData[mPosition++] = value;
321 if (mPosition >= mLength)
322 mPosition = 0;
323}
324
325void CircularBuffer::copyTo(unsigned long *data, unsigned long length)
326{
327 memcpy(data, mData + mPosition, (length - mPosition) * sizeof(unsigned long));
328 // Copy the wrapped part
329 if (mPosition)
330 memcpy(data + mPosition, mData, mPosition * sizeof(unsigned long));
331}
332
333void SubMetric::query(unsigned long *data, unsigned long count)
334{
335 copyTo(data, count);
336}
337
338void Metric::query(unsigned long **data, unsigned long *count)
339{
340 unsigned long length;
341 unsigned long *tmpData;
342
343 length = mSubMetric->length();
344 if (length)
345 {
346 tmpData = (unsigned long*)RTMemAlloc(sizeof(*tmpData)*length);
347 mSubMetric->query(tmpData, length);
348 if (mAggregate)
349 {
350 *count = 1;
351 *data = (unsigned long*)RTMemAlloc(sizeof(**data));
352 **data = mAggregate->compute(tmpData, length);
353 }
354 else
355 {
356 *count = length;
357 *data = tmpData;
358 }
359 }
360 else
361 {
362 *count = 0;
363 *data = 0;
364 }
365}
366
367unsigned long AggregateAvg::compute(unsigned long *data, unsigned long length)
368{
369 return 0;
370}
371
372const char * AggregateAvg::getName()
373{
374 return "avg";
375}
376
377unsigned long AggregateMin::compute(unsigned long *data, unsigned long length)
378{
379 return 0;
380}
381
382const char * AggregateMin::getName()
383{
384 return "min";
385}
386
387unsigned long AggregateMax::compute(unsigned long *data, unsigned long length)
388{
389 return 0;
390}
391
392const char * AggregateMax::getName()
393{
394 return "max";
395}
396
397Filter::Filter(ComSafeArrayIn(const BSTR, metricNames),
398 ComSafeArrayIn(IUnknown *, objects))
399{
400 com::SafeIfaceArray <IUnknown> objectArray(ComSafeArrayInArg(objects));
401 com::SafeArray <BSTR> nameArray(ComSafeArrayInArg(metricNames));
402 for (size_t i = 0; i < objectArray.size(); ++i)
403 processMetricList(std::string(com::Utf8Str(nameArray[i])), objectArray[i]);
404}
405
406void Filter::processMetricList(const std::string &name, const IUnknown *object)
407{
408 std::string::size_type startPos = 0;
409
410 for (std::string::size_type pos = name.find(",");
411 pos != std::string::npos;
412 pos = name.find(",", startPos))
413 {
414 mElements.push_back(std::make_pair(object, name.substr(startPos, pos - startPos)));
415 startPos = pos + 1;
416 }
417 mElements.push_back(std::make_pair(object, name.substr(startPos)));
418}
419
420bool Filter::match(const IUnknown *object, const std::string &name) const
421{
422 return true;
423}
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