VirtualBox

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

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

iprt::MiniString -> RTCString.

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