VirtualBox

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

Last change on this file since 26270 was 26128, checked in by vboxsync, 15 years ago

Main/Performance: Another burn fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/* $Id: Performance.h 26128 2010-02-01 14:48:59Z vboxsync $ */
2
3/** @file
4 *
5 * VBox Performance Classes declaration.
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
25#include <VBox/com/defs.h>
26#include <VBox/com/ptr.h>
27#include <VBox/com/string.h>
28
29#include <iprt/types.h>
30#include <iprt/err.h>
31
32#include <algorithm>
33#include <functional> /* For std::fun_ptr in testcase */
34#include <list>
35#include <vector>
36
37namespace pm
38{
39 /* CPU load is measured in 1/1000 of per cent. */
40 const uint64_t PM_CPU_LOAD_MULTIPLIER = UINT64_C(100000);
41
42 /* Sub Metrics **********************************************************/
43 class CircularBuffer
44 {
45 public:
46 CircularBuffer() : mData(0), mLength(0), mEnd(0), mWrapped(false) {};
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 /* Collector Hardware Abstraction Layer *********************************/
75 enum {
76 COLLECT_NONE = 0x0,
77 COLLECT_CPU_LOAD = 0x1,
78 COLLECT_RAM_USAGE = 0x2
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 collectProcessCpuLoad(RTPROCESS process)
94 { findProcess(process).second |= COLLECT_CPU_LOAD; }
95 void collectProcessRamUsage(RTPROCESS process)
96 { findProcess(process).second |= COLLECT_RAM_USAGE; }
97 bool isHostCpuLoadCollected() const
98 { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
99 bool isHostRamUsageCollected() const
100 { return (mHostFlags & COLLECT_RAM_USAGE) != 0; }
101 bool isProcessCpuLoadCollected(RTPROCESS process)
102 { return (findProcess(process).second & COLLECT_CPU_LOAD) != 0; }
103 bool isProcessRamUsageCollected(RTPROCESS process)
104 { return (findProcess(process).second & COLLECT_RAM_USAGE) != 0; }
105 void getProcesses(std::vector<RTPROCESS>& processes) const
106 {
107 processes.clear();
108 processes.reserve(mProcesses.size());
109 for (ProcessList::const_iterator it = mProcesses.begin(); it != mProcesses.end(); it++)
110 processes.push_back(it->first);
111 }
112 const ProcessList& getProcessFlags() const
113 {
114 return mProcesses;
115 }
116 private:
117 HintFlags mHostFlags;
118 ProcessList mProcesses;
119
120 ProcessFlagsPair& findProcess(RTPROCESS process)
121 {
122 ProcessList::iterator it;
123 for (it = mProcesses.begin(); it != mProcesses.end(); it++)
124 if (it->first == process)
125 return *it;
126
127 /* Not found -- add new */
128 mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE));
129 return mProcesses.back();
130 }
131 };
132
133 class CollectorHAL
134 {
135 public:
136 virtual ~CollectorHAL() { };
137 virtual int preCollect(const CollectorHints& /* hints */) { return VINF_SUCCESS; }
138 /** Returns averaged CPU usage in 1/1000th per cent across all host's CPUs. */
139 virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
140 /** Returns the average frequency in MHz across all host's CPUs. */
141 virtual int getHostCpuMHz(ULONG *mhz);
142 /** Returns the amount of physical memory in kilobytes. */
143 virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available) = 0;
144 /** Returns CPU usage in 1/1000th per cent by a particular process. */
145 virtual int getProcessCpuLoad(RTPROCESS process, ULONG *user, ULONG *kernel);
146 /** Returns the amount of memory used by a process in kilobytes. */
147 virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used) = 0;
148
149 /** Returns CPU usage counters in platform-specific units. */
150 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
151 /** Returns process' CPU usage counter in platform-specific units. */
152 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
153 };
154
155 extern CollectorHAL *createHAL();
156
157 /* Base Metrics *********************************************************/
158 class BaseMetric
159 {
160 public:
161 BaseMetric(CollectorHAL *hal, const char *name, ComPtr<IUnknown> object)
162 : mHAL(hal), mPeriod(0), mLength(0), mName(name), mObject(object), mLastSampleTaken(0), mEnabled(false) {};
163 virtual ~BaseMetric() {};
164
165 virtual void init(ULONG period, ULONG length) = 0;
166 virtual void preCollect(CollectorHints& hints) = 0;
167 virtual void collect() = 0;
168 virtual const char *getUnit() = 0;
169 virtual ULONG getMinValue() = 0;
170 virtual ULONG getMaxValue() = 0;
171 virtual ULONG getScale() = 0;
172
173 bool collectorBeat(uint64_t nowAt);
174
175 void enable() { mEnabled = true; };
176 void disable() { mEnabled = false; };
177
178 bool isEnabled() { return mEnabled; };
179 ULONG getPeriod() { return mPeriod; };
180 ULONG getLength() { return mLength; };
181 const char *getName() { return mName; };
182 ComPtr<IUnknown> getObject() { return mObject; };
183 bool associatedWith(ComPtr<IUnknown> object) { return mObject == object; };
184
185 protected:
186 CollectorHAL *mHAL;
187 ULONG mPeriod;
188 ULONG mLength;
189 const char *mName;
190 ComPtr<IUnknown> mObject;
191 uint64_t mLastSampleTaken;
192 bool mEnabled;
193 };
194
195 class HostCpuLoad : public BaseMetric
196 {
197 public:
198 HostCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
199 : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {};
200 ~HostCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
201
202 void init(ULONG period, ULONG length);
203
204 void collect();
205 const char *getUnit() { return "%"; };
206 ULONG getMinValue() { return 0; };
207 ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
208 ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
209
210 protected:
211 SubMetric *mUser;
212 SubMetric *mKernel;
213 SubMetric *mIdle;
214 };
215
216 class HostCpuLoadRaw : public HostCpuLoad
217 {
218 public:
219 HostCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
220 : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {};
221
222 void preCollect(CollectorHints& hints);
223 void collect();
224 private:
225 uint64_t mUserPrev;
226 uint64_t mKernelPrev;
227 uint64_t mIdlePrev;
228 };
229
230 class HostCpuMhz : public BaseMetric
231 {
232 public:
233 HostCpuMhz(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *mhz)
234 : BaseMetric(hal, "CPU/MHz", object), mMHz(mhz) {};
235 ~HostCpuMhz() { delete mMHz; };
236
237 void init(ULONG period, ULONG length);
238 void preCollect(CollectorHints& /* hints */) {}
239 void collect();
240 const char *getUnit() { return "MHz"; };
241 ULONG getMinValue() { return 0; };
242 ULONG getMaxValue() { return INT32_MAX; };
243 ULONG getScale() { return 1; }
244 private:
245 SubMetric *mMHz;
246 };
247
248 class HostRamUsage : public BaseMetric
249 {
250 public:
251 HostRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available)
252 : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mUsed(used), mAvailable(available) {};
253 ~HostRamUsage() { delete mTotal; delete mUsed; delete mAvailable; };
254
255 void init(ULONG period, ULONG length);
256 void preCollect(CollectorHints& hints);
257 void collect();
258 const char *getUnit() { return "kB"; };
259 ULONG getMinValue() { return 0; };
260 ULONG getMaxValue() { return INT32_MAX; };
261 ULONG getScale() { return 1; }
262 private:
263 SubMetric *mTotal;
264 SubMetric *mUsed;
265 SubMetric *mAvailable;
266 };
267
268 class MachineCpuLoad : public BaseMetric
269 {
270 public:
271 MachineCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
272 : BaseMetric(hal, "CPU/Load", object), mProcess(process), mUser(user), mKernel(kernel) {};
273 ~MachineCpuLoad() { delete mUser; delete mKernel; };
274
275 void init(ULONG period, ULONG length);
276 void collect();
277 const char *getUnit() { return "%"; };
278 ULONG getMinValue() { return 0; };
279 ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
280 ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
281 protected:
282 RTPROCESS mProcess;
283 SubMetric *mUser;
284 SubMetric *mKernel;
285 };
286
287 class MachineCpuLoadRaw : public MachineCpuLoad
288 {
289 public:
290 MachineCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
291 : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {};
292
293 void preCollect(CollectorHints& hints);
294 void collect();
295 private:
296 uint64_t mHostTotalPrev;
297 uint64_t mProcessUserPrev;
298 uint64_t mProcessKernelPrev;
299 };
300
301 class MachineRamUsage : public BaseMetric
302 {
303 public:
304 MachineRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
305 : BaseMetric(hal, "RAM/Usage", object), mProcess(process), mUsed(used) {};
306 ~MachineRamUsage() { delete mUsed; };
307
308 void init(ULONG period, ULONG length);
309 void preCollect(CollectorHints& hints);
310 void collect();
311 const char *getUnit() { return "kB"; };
312 ULONG getMinValue() { return 0; };
313 ULONG getMaxValue() { return INT32_MAX; };
314 ULONG getScale() { return 1; }
315 private:
316 RTPROCESS mProcess;
317 SubMetric *mUsed;
318 };
319
320 /* Aggregate Functions **************************************************/
321 class Aggregate
322 {
323 public:
324 virtual ULONG compute(ULONG *data, ULONG length) = 0;
325 virtual const char *getName() = 0;
326 };
327
328 class AggregateAvg : public Aggregate
329 {
330 public:
331 virtual ULONG compute(ULONG *data, ULONG length);
332 virtual const char *getName();
333 };
334
335 class AggregateMin : public Aggregate
336 {
337 public:
338 virtual ULONG compute(ULONG *data, ULONG length);
339 virtual const char *getName();
340 };
341
342 class AggregateMax : public Aggregate
343 {
344 public:
345 virtual ULONG compute(ULONG *data, ULONG length);
346 virtual const char *getName();
347 };
348
349 /* Metric Class *********************************************************/
350 class Metric
351 {
352 public:
353 Metric(BaseMetric *baseMetric, SubMetric *subMetric, Aggregate *aggregate) :
354 mName(subMetric->getName()), mBaseMetric(baseMetric), mSubMetric(subMetric), mAggregate(aggregate)
355 {
356 if (mAggregate)
357 {
358 mName.append(":");
359 mName.append(mAggregate->getName());
360 }
361 }
362
363 ~Metric()
364 {
365 delete mAggregate;
366 }
367 bool associatedWith(ComPtr<IUnknown> object) { return getObject() == object; };
368
369 const char *getName() { return mName.c_str(); };
370 ComPtr<IUnknown> getObject() { return mBaseMetric->getObject(); };
371 const char *getDescription()
372 { return mAggregate ? "" : mSubMetric->getDescription(); };
373 const char *getUnit() { return mBaseMetric->getUnit(); };
374 ULONG getMinValue() { return mBaseMetric->getMinValue(); };
375 ULONG getMaxValue() { return mBaseMetric->getMaxValue(); };
376 ULONG getPeriod() { return mBaseMetric->getPeriod(); };
377 ULONG getLength()
378 { return mAggregate ? 1 : mBaseMetric->getLength(); };
379 ULONG getScale() { return mBaseMetric->getScale(); }
380 void query(ULONG **data, ULONG *count, ULONG *sequenceNumber);
381
382 private:
383 iprt::MiniString mName;
384 BaseMetric *mBaseMetric;
385 SubMetric *mSubMetric;
386 Aggregate *mAggregate;
387 };
388
389 /* Filter Class *********************************************************/
390
391 class Filter
392 {
393 public:
394 Filter(ComSafeArrayIn(IN_BSTR, metricNames),
395 ComSafeArrayIn(IUnknown * , objects));
396 static bool patternMatch(const char *pszPat, const char *pszName,
397 bool fSeenColon = false);
398 bool match(const ComPtr<IUnknown> object, const iprt::MiniString &name) const;
399 private:
400 void init(ComSafeArrayIn(IN_BSTR, metricNames),
401 ComSafeArrayIn(IUnknown * , objects));
402
403 typedef std::pair<const ComPtr<IUnknown>, const iprt::MiniString> FilterElement;
404 typedef std::list<FilterElement> ElementList;
405
406 ElementList mElements;
407
408 void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object);
409 };
410}
411
412/* 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