VirtualBox

source: vbox/trunk/src/VBox/Main/include/Performance.h@ 36036

Last change on this file since 36036 was 36036, checked in by vboxsync, 14 years ago

indent

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.2 KB
Line 
1/* $Id: Performance.h 36036 2011-02-21 15:03:32Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Performance Classes declaration.
6 */
7
8/*
9 * Copyright (C) 2008 Oracle Corporation
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#ifndef ___performance_h
20#define ___performance_h
21
22#include <VBox/com/defs.h>
23#include <VBox/com/ptr.h>
24#include <VBox/com/string.h>
25#include <VBox/com/VirtualBox.h>
26
27#include <iprt/types.h>
28#include <iprt/err.h>
29
30#include <algorithm>
31#include <functional> /* For std::fun_ptr in testcase */
32#include <list>
33#include <vector>
34
35/* Forward decl. */
36class Machine;
37
38namespace pm
39{
40 /* CPU load is measured in 1/1000 of per cent. */
41 const uint64_t PM_CPU_LOAD_MULTIPLIER = UINT64_C(100000);
42
43 /* Sub Metrics **********************************************************/
44 class CircularBuffer
45 {
46 public:
47 CircularBuffer() : mData(0), mLength(0), mEnd(0), mWrapped(false) {};
48 void init(ULONG length);
49 ULONG length();
50 ULONG getSequenceNumber() { return mSequenceNumber; }
51 void put(ULONG value);
52 void copyTo(ULONG *data);
53 private:
54 ULONG *mData;
55 ULONG mLength;
56 ULONG mEnd;
57 ULONG mSequenceNumber;
58 bool mWrapped;
59 };
60
61 class SubMetric : public CircularBuffer
62 {
63 public:
64 SubMetric(const char *name, const char *description)
65 : mName(name), mDescription(description) {};
66 void query(ULONG *data);
67 const char *getName() { return mName; };
68 const char *getDescription() { return mDescription; };
69 private:
70 const char *mName;
71 const char *mDescription;
72 };
73
74
75 /* Collector Hardware Abstraction Layer *********************************/
76 enum {
77 COLLECT_NONE = 0x0,
78 COLLECT_CPU_LOAD = 0x1,
79 COLLECT_RAM_USAGE = 0x2
80 };
81 typedef int HintFlags;
82 typedef std::pair<RTPROCESS, HintFlags> ProcessFlagsPair;
83
84 class CollectorHints
85 {
86 public:
87 typedef std::list<ProcessFlagsPair> ProcessList;
88
89 CollectorHints() : mHostFlags(COLLECT_NONE) {}
90 void collectHostCpuLoad()
91 { mHostFlags |= COLLECT_CPU_LOAD; }
92 void collectHostRamUsage()
93 { mHostFlags |= COLLECT_RAM_USAGE; }
94 void collectProcessCpuLoad(RTPROCESS process)
95 { findProcess(process).second |= COLLECT_CPU_LOAD; }
96 void collectProcessRamUsage(RTPROCESS process)
97 { findProcess(process).second |= COLLECT_RAM_USAGE; }
98 bool isHostCpuLoadCollected() const
99 { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
100 bool isHostRamUsageCollected() const
101 { return (mHostFlags & COLLECT_RAM_USAGE) != 0; }
102 bool isProcessCpuLoadCollected(RTPROCESS process)
103 { return (findProcess(process).second & COLLECT_CPU_LOAD) != 0; }
104 bool isProcessRamUsageCollected(RTPROCESS process)
105 { return (findProcess(process).second & COLLECT_RAM_USAGE) != 0; }
106 void getProcesses(std::vector<RTPROCESS>& processes) const
107 {
108 processes.clear();
109 processes.reserve(mProcesses.size());
110 for (ProcessList::const_iterator it = mProcesses.begin(); it != mProcesses.end(); it++)
111 processes.push_back(it->first);
112 }
113 const ProcessList& getProcessFlags() const
114 {
115 return mProcesses;
116 }
117 private:
118 HintFlags mHostFlags;
119 ProcessList mProcesses;
120
121 ProcessFlagsPair& findProcess(RTPROCESS process)
122 {
123 ProcessList::iterator it;
124 for (it = mProcesses.begin(); it != mProcesses.end(); it++)
125 if (it->first == process)
126 return *it;
127
128 /* Not found -- add new */
129 mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE));
130 return mProcesses.back();
131 }
132 };
133
134 class CollectorHAL
135 {
136 public:
137 CollectorHAL() : mMemAllocVMM(0), mMemFreeVMM(0), mMemBalloonedVMM(0), mMemSharedVMM(0) {};
138 virtual ~CollectorHAL() { };
139 virtual int preCollect(const CollectorHints& /* hints */, uint64_t /* iTick */) { return VINF_SUCCESS; }
140 /** Returns averaged CPU usage in 1/1000th per cent across all host's CPUs. */
141 virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
142 /** Returns the average frequency in MHz across all host's CPUs. */
143 virtual int getHostCpuMHz(ULONG *mhz);
144 /** Returns the amount of physical memory in kilobytes. */
145 virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
146 /** Returns CPU usage in 1/1000th per cent by a particular process. */
147 virtual int getProcessCpuLoad(RTPROCESS process, ULONG *user, ULONG *kernel);
148 /** Returns the amount of memory used by a process in kilobytes. */
149 virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
150
151 /** Returns CPU usage counters in platform-specific units. */
152 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
153 /** Returns process' CPU usage counter in platform-specific units. */
154 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
155
156 /** Enable metrics collecting (if applicable) */
157 virtual int enable();
158 /** Disable metrics collecting (if applicable) */
159 virtual int disable();
160
161 virtual int setMemHypervisorStats(ULONG memAlloc, ULONG memFree, ULONG memBallooned, ULONG memShared)
162 {
163 mMemAllocVMM = memAlloc;
164 mMemFreeVMM = memFree;
165 mMemBalloonedVMM = memBallooned;
166 mMemSharedVMM = memShared;
167 return S_OK;
168 }
169
170 virtual void getMemHypervisorStats(ULONG *pMemAlloc, ULONG *pMemFree, ULONG *pMemBallooned, ULONG *pMemShared)
171 {
172 *pMemAlloc = mMemAllocVMM;
173 *pMemFree = mMemFreeVMM;
174 *pMemBallooned = mMemBalloonedVMM;
175 *pMemShared = mMemSharedVMM;
176 }
177
178 private:
179 ULONG mMemAllocVMM;
180 ULONG mMemFreeVMM;
181 ULONG mMemBalloonedVMM;
182 ULONG mMemSharedVMM;
183 };
184
185 class CollectorGuestHAL : public CollectorHAL
186 {
187 public:
188 CollectorGuestHAL(Machine *machine, CollectorHAL *hostHAL);
189 ~CollectorGuestHAL();
190
191 virtual int preCollect(const CollectorHints& hints, uint64_t iTick);
192
193 /** Enable metrics collecting (if applicable) */
194 virtual int enable();
195 /** Disable metrics collecting (if applicable) */
196 virtual int disable();
197
198 /** Return guest cpu absolute load values (0-100). */
199 void getGuestCpuLoad(ULONG *pulCpuUser, ULONG *pulCpuKernel, ULONG *pulCpuIdle)
200 {
201 *pulCpuUser = mCpuUser;
202 *pulCpuKernel = mCpuKernel;
203 *pulCpuIdle = mCpuIdle;
204 }
205
206 /** Return guest memory information in KB. */
207 void getGuestMemLoad(ULONG *pulMemTotal, ULONG *pulMemFree, ULONG *pulMemBalloon, ULONG *pulMemShared, ULONG *pulMemCache, ULONG *pulPageTotal)
208 {
209 *pulMemTotal = mMemTotal;
210 *pulMemFree = mMemFree;
211 *pulMemBalloon = mMemBalloon;
212 *pulMemShared = mMemShared;
213 *pulMemCache = mMemCache;
214 *pulPageTotal = mPageTotal;
215 }
216
217
218 protected:
219 uint32_t cEnabled;
220 Machine *mMachine;
221 ComPtr<IConsole> mConsole;
222 ComPtr<IGuest> mGuest;
223 uint64_t mLastTick;
224
225 CollectorHAL *mHostHAL;
226
227 ULONG mCpuUser;
228 ULONG mCpuKernel;
229 ULONG mCpuIdle;
230 ULONG mMemTotal;
231 ULONG mMemFree;
232 ULONG mMemBalloon;
233 ULONG mMemShared;
234 ULONG mMemCache;
235 ULONG mPageTotal;
236
237 private:
238 static uint32_t cVMsEnabled;
239 };
240
241 extern CollectorHAL *createHAL();
242
243 /* Base Metrics *********************************************************/
244 class BaseMetric
245 {
246 public:
247 BaseMetric(CollectorHAL *hal, const char *name, ComPtr<IUnknown> object)
248 : mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object), mLastSampleTaken(0), mEnabled(false) {};
249 virtual ~BaseMetric() {};
250
251 virtual void init(ULONG period, ULONG length) = 0;
252 virtual void preCollect(CollectorHints& hints, uint64_t iTick) = 0;
253 virtual void collect() = 0;
254 virtual const char *getUnit() = 0;
255 virtual ULONG getMinValue() = 0;
256 virtual ULONG getMaxValue() = 0;
257 virtual ULONG getScale() = 0;
258
259 bool collectorBeat(uint64_t nowAt);
260
261 void enable()
262 {
263 mEnabled = true;
264 mHAL->enable();
265 };
266 void disable()
267 {
268 mHAL->disable();
269 mEnabled = false;
270 };
271
272 bool isEnabled() { return mEnabled; };
273 ULONG getPeriod() { return mPeriod; };
274 ULONG getLength() { return mLength; };
275 const char *getName() { return mName; };
276 ComPtr<IUnknown> getObject() { return mObject; };
277 bool associatedWith(ComPtr<IUnknown> object) { return mObject == object; };
278
279 protected:
280 ULONG mPeriod;
281 ULONG mLength;
282 CollectorHAL *mHAL;
283 const char *mName;
284 ComPtr<IUnknown> mObject;
285 uint64_t mLastSampleTaken;
286 bool mEnabled;
287 };
288
289 class HostCpuLoad : public BaseMetric
290 {
291 public:
292 HostCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
293 : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {};
294 ~HostCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
295
296 void init(ULONG period, ULONG length);
297
298 void collect();
299 const char *getUnit() { return "%"; };
300 ULONG getMinValue() { return 0; };
301 ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
302 ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
303
304 protected:
305 SubMetric *mUser;
306 SubMetric *mKernel;
307 SubMetric *mIdle;
308 };
309
310 class HostCpuLoadRaw : public HostCpuLoad
311 {
312 public:
313 HostCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
314 : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {};
315
316 void preCollect(CollectorHints& hints, uint64_t iTick);
317 void collect();
318 private:
319 uint64_t mUserPrev;
320 uint64_t mKernelPrev;
321 uint64_t mIdlePrev;
322 };
323
324 class HostCpuMhz : public BaseMetric
325 {
326 public:
327 HostCpuMhz(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *mhz)
328 : BaseMetric(hal, "CPU/MHz", object), mMHz(mhz) {};
329 ~HostCpuMhz() { delete mMHz; };
330
331 void init(ULONG period, ULONG length);
332 void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {}
333 void collect();
334 const char *getUnit() { return "MHz"; };
335 ULONG getMinValue() { return 0; };
336 ULONG getMaxValue() { return INT32_MAX; };
337 ULONG getScale() { return 1; }
338 private:
339 SubMetric *mMHz;
340 };
341
342 class HostRamUsage : public BaseMetric
343 {
344 public:
345 HostRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available)
346 : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mUsed(used), mAvailable(available) {};
347 ~HostRamUsage() { delete mTotal; delete mUsed; delete mAvailable; };
348
349 void init(ULONG period, ULONG length);
350 void preCollect(CollectorHints& hints, uint64_t iTick);
351 void collect();
352 const char *getUnit() { return "kB"; };
353 ULONG getMinValue() { return 0; };
354 ULONG getMaxValue() { return INT32_MAX; };
355 ULONG getScale() { return 1; }
356 private:
357 SubMetric *mTotal;
358 SubMetric *mUsed;
359 SubMetric *mAvailable;
360 };
361
362 class HostRamVmm : public BaseMetric
363 {
364 public:
365 HostRamVmm(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *allocVMM, SubMetric *freeVMM, SubMetric *balloonVMM, SubMetric *sharedVMM)
366 : BaseMetric(hal, "RAM/VMM", object), mAllocVMM(allocVMM), mFreeVMM(freeVMM), mBalloonVMM(balloonVMM), mSharedVMM(sharedVMM) {};
367 ~HostRamVmm() { delete mAllocVMM; delete mFreeVMM; delete mBalloonVMM; delete mSharedVMM; };
368
369 void init(ULONG period, ULONG length);
370 void preCollect(CollectorHints& hints, uint64_t iTick);
371 void collect();
372 const char *getUnit() { return "kB"; };
373 ULONG getMinValue() { return 0; };
374 ULONG getMaxValue() { return INT32_MAX; };
375 ULONG getScale() { return 1; }
376 private:
377 SubMetric *mAllocVMM;
378 SubMetric *mFreeVMM;
379 SubMetric *mBalloonVMM;
380 SubMetric *mSharedVMM;
381 };
382
383 class MachineCpuLoad : public BaseMetric
384 {
385 public:
386 MachineCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
387 : BaseMetric(hal, "CPU/Load", object), mProcess(process), mUser(user), mKernel(kernel) {};
388 ~MachineCpuLoad() { delete mUser; delete mKernel; };
389
390 void init(ULONG period, ULONG length);
391 void collect();
392 const char *getUnit() { return "%"; };
393 ULONG getMinValue() { return 0; };
394 ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
395 ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
396 protected:
397 RTPROCESS mProcess;
398 SubMetric *mUser;
399 SubMetric *mKernel;
400 };
401
402 class MachineCpuLoadRaw : public MachineCpuLoad
403 {
404 public:
405 MachineCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
406 : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {};
407
408 void preCollect(CollectorHints& hints, uint64_t iTick);
409 void collect();
410 private:
411 uint64_t mHostTotalPrev;
412 uint64_t mProcessUserPrev;
413 uint64_t mProcessKernelPrev;
414 };
415
416 class MachineRamUsage : public BaseMetric
417 {
418 public:
419 MachineRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
420 : BaseMetric(hal, "RAM/Usage", object), mProcess(process), mUsed(used) {};
421 ~MachineRamUsage() { delete mUsed; };
422
423 void init(ULONG period, ULONG length);
424 void preCollect(CollectorHints& hints, uint64_t iTick);
425 void collect();
426 const char *getUnit() { return "kB"; };
427 ULONG getMinValue() { return 0; };
428 ULONG getMaxValue() { return INT32_MAX; };
429 ULONG getScale() { return 1; }
430 private:
431 RTPROCESS mProcess;
432 SubMetric *mUsed;
433 };
434
435
436 class GuestCpuLoad : public BaseMetric
437 {
438 public:
439 GuestCpuLoad(CollectorGuestHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
440 : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle), mGuestHAL(hal) {};
441 ~GuestCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
442
443 void init(ULONG period, ULONG length);
444 void preCollect(CollectorHints& hints, uint64_t iTick);
445 void collect();
446 const char *getUnit() { return "%"; };
447 ULONG getMinValue() { return 0; };
448 ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
449 ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
450 protected:
451 SubMetric *mUser;
452 SubMetric *mKernel;
453 SubMetric *mIdle;
454 CollectorGuestHAL *mGuestHAL;
455 };
456
457 class GuestRamUsage : public BaseMetric
458 {
459 public:
460 GuestRamUsage(CollectorGuestHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *free, SubMetric *balloon, SubMetric *shared, SubMetric *cache, SubMetric *pagedtotal)
461 : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mFree(free), mBallooned(balloon), mCache(cache), mPagedTotal(pagedtotal), mShared(shared), mGuestHAL(hal) {};
462 ~GuestRamUsage() { delete mTotal; delete mFree; delete mBallooned; delete mShared; delete mCache; delete mPagedTotal; };
463
464 void init(ULONG period, ULONG length);
465 void preCollect(CollectorHints& hints, uint64_t iTick);
466 void collect();
467 const char *getUnit() { return "kB"; };
468 ULONG getMinValue() { return 0; };
469 ULONG getMaxValue() { return INT32_MAX; };
470 ULONG getScale() { return 1; }
471 private:
472 SubMetric *mTotal, *mFree, *mBallooned, *mCache, *mPagedTotal, *mShared;
473 CollectorGuestHAL *mGuestHAL;
474 };
475
476 /* Aggregate Functions **************************************************/
477 class Aggregate
478 {
479 public:
480 virtual ULONG compute(ULONG *data, ULONG length) = 0;
481 virtual const char *getName() = 0;
482 };
483
484 class AggregateAvg : public Aggregate
485 {
486 public:
487 virtual ULONG compute(ULONG *data, ULONG length);
488 virtual const char *getName();
489 };
490
491 class AggregateMin : public Aggregate
492 {
493 public:
494 virtual ULONG compute(ULONG *data, ULONG length);
495 virtual const char *getName();
496 };
497
498 class AggregateMax : public Aggregate
499 {
500 public:
501 virtual ULONG compute(ULONG *data, ULONG length);
502 virtual const char *getName();
503 };
504
505 /* Metric Class *********************************************************/
506 class Metric
507 {
508 public:
509 Metric(BaseMetric *baseMetric, SubMetric *subMetric, Aggregate *aggregate) :
510 mName(subMetric->getName()), mBaseMetric(baseMetric), mSubMetric(subMetric), mAggregate(aggregate)
511 {
512 if (mAggregate)
513 {
514 mName.append(":");
515 mName.append(mAggregate->getName());
516 }
517 }
518
519 ~Metric()
520 {
521 delete mAggregate;
522 }
523 bool associatedWith(ComPtr<IUnknown> object) { return getObject() == object; };
524
525 const char *getName() { return mName.c_str(); };
526 ComPtr<IUnknown> getObject() { return mBaseMetric->getObject(); };
527 const char *getDescription()
528 { return mAggregate ? "" : mSubMetric->getDescription(); };
529 const char *getUnit() { return mBaseMetric->getUnit(); };
530 ULONG getMinValue() { return mBaseMetric->getMinValue(); };
531 ULONG getMaxValue() { return mBaseMetric->getMaxValue(); };
532 ULONG getPeriod() { return mBaseMetric->getPeriod(); };
533 ULONG getLength()
534 { return mAggregate ? 1 : mBaseMetric->getLength(); };
535 ULONG getScale() { return mBaseMetric->getScale(); }
536 void query(ULONG **data, ULONG *count, ULONG *sequenceNumber);
537
538 private:
539 iprt::MiniString mName;
540 BaseMetric *mBaseMetric;
541 SubMetric *mSubMetric;
542 Aggregate *mAggregate;
543 };
544
545 /* Filter Class *********************************************************/
546
547 class Filter
548 {
549 public:
550 Filter(ComSafeArrayIn(IN_BSTR, metricNames),
551 ComSafeArrayIn(IUnknown * , objects));
552 static bool patternMatch(const char *pszPat, const char *pszName,
553 bool fSeenColon = false);
554 bool match(const ComPtr<IUnknown> object, const iprt::MiniString &name) const;
555 private:
556 void init(ComSafeArrayIn(IN_BSTR, metricNames),
557 ComSafeArrayIn(IUnknown * , objects));
558
559 typedef std::pair<const ComPtr<IUnknown>, const iprt::MiniString> FilterElement;
560 typedef std::list<FilterElement> ElementList;
561
562 ElementList mElements;
563
564 void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object);
565 };
566}
567#endif /* ___performance_h */
568/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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