VirtualBox

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

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

Main/Metrics: Memory leak fixes

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