VirtualBox

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

Last change on this file since 10854 was 10753, checked in by vboxsync, 16 years ago

Stubs for all platforms. Implementation of host CPU load and RAM usage counters for Windows. Locking. Fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
Line 
1/* $Id: Performance.cpp 10753 2008-07-18 19:22:21Z 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(ComPtr<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(ComPtr<IUnknown> object, SubMetric *mhz)
43{
44 Assert(mHAL);
45 return new HostCpuMhz(mHAL, object, mhz);
46}
47BaseMetric *MetricFactory::createHostRamUsage(ComPtr<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(ComPtr<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(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
58{
59 Assert(mHAL);
60 return new MachineRamUsage(mHAL, object, process, used);
61}
62
63// Stubs for non-pure virtual methods
64
65int CollectorHAL::getHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle)
66{
67 return E_NOTIMPL;
68}
69
70int CollectorHAL::getProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel)
71{
72 return E_NOTIMPL;
73}
74
75int CollectorHAL::getRawHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle)
76{
77 return E_NOTIMPL;
78}
79
80int CollectorHAL::getRawProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel)
81{
82 return E_NOTIMPL;
83}
84
85void BaseMetric::collectorBeat(uint64_t nowAt)
86{
87 if (isEnabled())
88 {
89 if (nowAt - mLastSampleTaken >= mPeriod * 1000)
90 {
91 mLastSampleTaken = nowAt;
92 collect();
93 }
94 }
95}
96
97void HostCpuLoad::init(unsigned long period, unsigned long length)
98{
99 mPeriod = period;
100 mLength = length;
101 mUser->init(mLength);
102 mKernel->init(mLength);
103 mIdle->init(mLength);
104}
105
106void HostCpuLoad::collect()
107{
108 unsigned long user, kernel, idle;
109 int rc = mHAL->getHostCpuLoad(&user, &kernel, &idle);
110 if (RT_SUCCESS(rc))
111 {
112 mUser->put(user);
113 mKernel->put(kernel);
114 mIdle->put(idle);
115 }
116}
117
118void HostCpuLoadRaw::collect()
119{
120 unsigned long user, kernel, idle;
121 unsigned long userDiff, kernelDiff, idleDiff, totalDiff;
122
123 int rc = mHAL->getRawHostCpuLoad(&user, &kernel, &idle);
124 if (RT_SUCCESS(rc))
125 {
126 userDiff = user - mUserPrev;
127 kernelDiff = kernel - mKernelPrev;
128 idleDiff = idle - mIdlePrev;
129 totalDiff = userDiff + kernelDiff + idleDiff;
130
131 mUser->put(PM_CPU_LOAD_MULTIPLIER * userDiff / totalDiff);
132 mKernel->put(PM_CPU_LOAD_MULTIPLIER * kernelDiff / totalDiff);
133 mIdle->put(PM_CPU_LOAD_MULTIPLIER * idleDiff / totalDiff);
134
135 mUserPrev = user;
136 mKernelPrev = kernel;
137 mIdlePrev = idle;
138 }
139}
140
141void HostCpuMhz::init(unsigned long period, unsigned long length)
142{
143 mPeriod = period;
144 mLength = length;
145 mMHz->init(mLength);
146}
147
148void HostCpuMhz::collect()
149{
150 unsigned long mhz;
151 int rc = mHAL->getHostCpuMHz(&mhz);
152 if (RT_SUCCESS(rc))
153 mMHz->put(mhz);
154}
155
156void HostRamUsage::init(unsigned long period, unsigned long length)
157{
158 mPeriod = period;
159 mLength = length;
160 mTotal->init(mLength);
161 mUsed->init(mLength);
162 mAvailable->init(mLength);
163}
164
165void HostRamUsage::collect()
166{
167 unsigned long total, used, available;
168 int rc = mHAL->getHostMemoryUsage(&total, &used, &available);
169 if (RT_SUCCESS(rc))
170 {
171 mTotal->put(total);
172 mUsed->put(used);
173 mAvailable->put(available);
174 }
175}
176
177
178
179void MachineCpuLoad::init(unsigned long period, unsigned long length)
180{
181 mPeriod = period;
182 mLength = length;
183 mUser->init(mLength);
184 mKernel->init(mLength);
185}
186
187void MachineCpuLoad::collect()
188{
189 unsigned long user, kernel;
190 int rc = mHAL->getProcessCpuLoad(mProcess, &user, &kernel);
191 if (RT_SUCCESS(rc))
192 {
193 mUser->put(user);
194 mKernel->put(kernel);
195 }
196}
197
198void MachineCpuLoadRaw::collect()
199{
200 unsigned long hostUser, hostKernel, hostIdle, hostTotal;
201 unsigned long processUser, processKernel;
202
203 int rc = mHAL->getRawHostCpuLoad(&hostUser, &hostKernel, &hostIdle);
204 if (RT_SUCCESS(rc))
205 {
206 hostTotal = hostUser + hostKernel + hostIdle;
207
208 rc = mHAL->getRawProcessCpuLoad(mProcess, &processUser, &processKernel);
209 AssertRC(rc);
210 if (RT_SUCCESS(rc))
211 {
212 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processUser - mProcessUserPrev) / (hostTotal - mHostTotalPrev));
213 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processKernel - mProcessKernelPrev ) / (hostTotal - mHostTotalPrev));
214
215 mHostTotalPrev = hostTotal;
216 mProcessUserPrev = processUser;
217 mProcessKernelPrev = processKernel;
218 }
219 }
220}
221
222void MachineRamUsage::init(unsigned long period, unsigned long length)
223{
224 mPeriod = period;
225 mLength = length;
226 mUsed->init(mLength);
227}
228
229void MachineRamUsage::collect()
230{
231 unsigned long used;
232 int rc = mHAL->getProcessMemoryUsage(mProcess, &used);
233 if (RT_SUCCESS(rc))
234 mUsed->put(used);
235}
236
237void CircularBuffer::init(unsigned long length)
238{
239 if (mData)
240 RTMemFree(mData);
241 mLength = length;
242 mData = (unsigned long *)RTMemAllocZ(length * sizeof(unsigned long));
243 mWrapped = false;
244 mEnd = 0;
245}
246
247unsigned long CircularBuffer::length()
248{
249 return mWrapped ? mLength : mEnd;
250}
251
252void CircularBuffer::put(unsigned long value)
253{
254 if (mData)
255 {
256 mData[mEnd++] = value;
257 if (mEnd >= mLength)
258 {
259 mEnd = 0;
260 mWrapped = true;
261 }
262 }
263}
264
265void CircularBuffer::copyTo(unsigned long *data)
266{
267 if (mWrapped)
268 {
269 memcpy(data, mData + mEnd, (mLength - mEnd) * sizeof(unsigned long));
270 // Copy the wrapped part
271 if (mEnd)
272 memcpy(data + mEnd, mData, mEnd * sizeof(unsigned long));
273 }
274 else
275 memcpy(data, mData, mEnd * sizeof(unsigned long));
276}
277
278void SubMetric::query(unsigned long *data)
279{
280 copyTo(data);
281}
282
283void Metric::query(unsigned long **data, unsigned long *count)
284{
285 unsigned long length;
286 unsigned long *tmpData;
287
288 length = mSubMetric->length();
289 if (length)
290 {
291 tmpData = (unsigned long*)RTMemAlloc(sizeof(*tmpData)*length);
292 mSubMetric->query(tmpData);
293 if (mAggregate)
294 {
295 *count = 1;
296 *data = (unsigned long*)RTMemAlloc(sizeof(**data));
297 **data = mAggregate->compute(tmpData, length);
298 RTMemFree(tmpData);
299 }
300 else
301 {
302 *count = length;
303 *data = tmpData;
304 }
305 }
306 else
307 {
308 *count = 0;
309 *data = 0;
310 }
311}
312
313unsigned long AggregateAvg::compute(unsigned long *data, unsigned long length)
314{
315 uint64_t tmp = 0;
316 for (unsigned long i = 0; i < length; ++i)
317 tmp += data[i];
318 return (unsigned long)(tmp / length);
319}
320
321const char * AggregateAvg::getName()
322{
323 return "avg";
324}
325
326unsigned long AggregateMin::compute(unsigned long *data, unsigned long length)
327{
328 unsigned long tmp = *data;
329 for (unsigned long i = 0; i < length; ++i)
330 if (data[i] < tmp)
331 tmp = data[i];
332 return tmp;
333}
334
335const char * AggregateMin::getName()
336{
337 return "min";
338}
339
340unsigned long AggregateMax::compute(unsigned long *data, unsigned long length)
341{
342 unsigned long tmp = *data;
343 for (unsigned long i = 0; i < length; ++i)
344 if (data[i] > tmp)
345 tmp = data[i];
346 return tmp;
347}
348
349const char * AggregateMax::getName()
350{
351 return "max";
352}
353
354Filter::Filter(ComSafeArrayIn(INPTR BSTR, metricNames),
355 ComSafeArrayIn(IUnknown *, objects))
356{
357 com::SafeIfaceArray <IUnknown> objectArray(ComSafeArrayInArg(objects));
358 com::SafeArray <INPTR BSTR> nameArray(ComSafeArrayInArg(metricNames));
359 if (objectArray.isNull())
360 {
361 if (nameArray.size())
362 {
363 for (size_t i = 0; i < nameArray.size(); ++i)
364 processMetricList(std::string(com::Utf8Str(nameArray[i])), ComPtr<IUnknown>());
365 }
366 else
367 processMetricList(std::string("*"), ComPtr<IUnknown>());
368 }
369 else
370 {
371 for (size_t i = 0; i < objectArray.size(); ++i)
372 switch (nameArray.size())
373 {
374 case 0:
375 processMetricList(std::string("*"), objectArray[i]);
376 break;
377 case 1:
378 processMetricList(std::string(com::Utf8Str(nameArray[0])), objectArray[i]);
379 break;
380 default:
381 processMetricList(std::string(com::Utf8Str(nameArray[i])), objectArray[i]);
382 break;
383 }
384 }
385}
386
387void Filter::processMetricList(const std::string &name, const ComPtr<IUnknown> object)
388{
389 std::string::size_type startPos = 0;
390
391 for (std::string::size_type pos = name.find(",");
392 pos != std::string::npos;
393 pos = name.find(",", startPos))
394 {
395 mElements.push_back(std::make_pair(object, name.substr(startPos, pos - startPos)));
396 startPos = pos + 1;
397 }
398 mElements.push_back(std::make_pair(object, name.substr(startPos)));
399}
400
401bool Filter::match(const ComPtr<IUnknown> object, const std::string &name) const
402{
403 ElementList::const_iterator it;
404
405 printf("Filter::match(%p, %s)\n", static_cast<const IUnknown*> (object), name.c_str());
406 for (it = mElements.begin(); it != mElements.end(); it++)
407 {
408 printf("...matching against(%p, %s)\n", static_cast<const IUnknown*> ((*it).first), (*it).second.c_str());
409 if ((*it).first.isNull() || (*it).first == object)
410 {
411 // Objects match, compare names
412 if ((*it).second == "*" || (*it).second == name)
413 {
414 printf("...found!\n");
415 return true;
416 }
417 }
418 }
419 printf("...no matches!\n");
420 return false;
421}
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