summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/include/Performance.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/include/Performance.h')
-rw-r--r--src/VBox/Main/include/Performance.h915
1 files changed, 915 insertions, 0 deletions
diff --git a/src/VBox/Main/include/Performance.h b/src/VBox/Main/include/Performance.h
new file mode 100644
index 00000000..1c092558
--- /dev/null
+++ b/src/VBox/Main/include/Performance.h
@@ -0,0 +1,915 @@
+/* $Id: Performance.h $ */
+/** @file
+ * VirtualBox Main - Performance Classes declaration.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef MAIN_INCLUDED_Performance_h
+#define MAIN_INCLUDED_Performance_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/com/defs.h>
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+#include <VBox/com/VirtualBox.h>
+
+#include <iprt/types.h>
+#include <iprt/err.h>
+#include <iprt/cpp/lock.h>
+
+#include <algorithm>
+#include <functional> /* For std::fun_ptr in testcase */
+#include <list>
+#include <vector>
+#include <queue>
+
+#include "MediumImpl.h"
+
+/* Forward decl. */
+class Machine;
+
+namespace pm
+{
+ /* CPU load is measured in 1/1000 of per cent. */
+ const uint64_t PM_CPU_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Network load is measured in 1/1000 of per cent. */
+ const uint64_t PM_NETWORK_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Disk load is measured in 1/1000 of per cent. */
+ const uint64_t PM_DISK_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Sampler precision in milliseconds. */
+ const uint64_t PM_SAMPLER_PRECISION_MS = 50;
+
+ /* Sub Metrics **********************************************************/
+ class CircularBuffer
+ {
+ public:
+ CircularBuffer() : mData(0), mLength(0), mEnd(0), mWrapped(false) {};
+ ~CircularBuffer() { if (mData) RTMemFree(mData); };
+ void init(ULONG length);
+ ULONG length();
+ ULONG getSequenceNumber() { return mSequenceNumber; }
+ void put(ULONG value);
+ void copyTo(ULONG *data);
+ private:
+ ULONG *mData;
+ ULONG mLength;
+ ULONG mEnd;
+ ULONG mSequenceNumber;
+ bool mWrapped;
+ };
+
+ class SubMetric : public CircularBuffer
+ {
+ public:
+ SubMetric(com::Utf8Str name, const char *description)
+ : mName(name), mDescription(description) {};
+ void query(ULONG *data);
+ const char *getName() { return mName.c_str(); };
+ const char *getDescription() { return mDescription; };
+ private:
+ const com::Utf8Str mName;
+ const char *mDescription;
+ };
+
+
+ enum {
+ COLLECT_NONE = 0x0,
+ COLLECT_CPU_LOAD = 0x1,
+ COLLECT_RAM_USAGE = 0x2,
+ COLLECT_GUEST_STATS = 0x4
+ };
+ typedef int HintFlags;
+ typedef std::pair<RTPROCESS, HintFlags> ProcessFlagsPair;
+
+ class CollectorHints
+ {
+ public:
+ typedef std::list<ProcessFlagsPair> ProcessList;
+
+ CollectorHints() : mHostFlags(COLLECT_NONE) {}
+ void collectHostCpuLoad()
+ { mHostFlags |= COLLECT_CPU_LOAD; }
+ void collectHostRamUsage()
+ { mHostFlags |= COLLECT_RAM_USAGE; }
+ void collectHostRamVmm()
+ { mHostFlags |= COLLECT_GUEST_STATS; }
+ void collectProcessCpuLoad(RTPROCESS process)
+ { findProcess(process).second |= COLLECT_CPU_LOAD; }
+ void collectProcessRamUsage(RTPROCESS process)
+ { findProcess(process).second |= COLLECT_RAM_USAGE; }
+ void collectGuestStats(RTPROCESS process)
+ { findProcess(process).second |= COLLECT_GUEST_STATS; }
+ bool isHostCpuLoadCollected() const
+ { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
+ bool isHostRamUsageCollected() const
+ { return (mHostFlags & COLLECT_RAM_USAGE) != 0; }
+ bool isHostRamVmmCollected() const
+ { return (mHostFlags & COLLECT_GUEST_STATS) != 0; }
+ bool isProcessCpuLoadCollected(RTPROCESS process)
+ { return (findProcess(process).second & COLLECT_CPU_LOAD) != 0; }
+ bool isProcessRamUsageCollected(RTPROCESS process)
+ { return (findProcess(process).second & COLLECT_RAM_USAGE) != 0; }
+ bool isGuestStatsCollected(RTPROCESS process)
+ { return (findProcess(process).second & COLLECT_GUEST_STATS) != 0; }
+ void getProcesses(std::vector<RTPROCESS>& processes) const
+ {
+ processes.clear();
+ processes.reserve(mProcesses.size());
+ for (ProcessList::const_iterator it = mProcesses.begin(); it != mProcesses.end(); ++it)
+ processes.push_back(it->first);
+ }
+ const ProcessList& getProcessFlags() const
+ {
+ return mProcesses;
+ }
+ private:
+ HintFlags mHostFlags;
+ ProcessList mProcesses;
+
+ ProcessFlagsPair& findProcess(RTPROCESS process)
+ {
+ ProcessList::iterator it;
+ for (it = mProcesses.begin(); it != mProcesses.end(); ++it)
+ if (it->first == process)
+ return *it;
+
+ /* Not found -- add new */
+ mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE));
+ return mProcesses.back();
+ }
+ };
+
+ /* Guest Collector Classes *********************************/
+ /*
+ * WARNING! The bits in the following masks must correspond to parameters
+ * of CollectorGuest::updateStats().
+ */
+ typedef enum
+ {
+ VMSTATMASK_NONE = 0x00000000,
+ VMSTATMASK_GUEST_CPUUSER = 0x00000001,
+ VMSTATMASK_GUEST_CPUKERNEL = 0x00000002,
+ VMSTATMASK_GUEST_CPUIDLE = 0x00000004,
+ VMSTATMASK_GUEST_MEMTOTAL = 0x00000008,
+ VMSTATMASK_GUEST_MEMFREE = 0x00000010,
+ VMSTATMASK_GUEST_MEMBALLOON = 0x00000020,
+ VMSTATMASK_GUEST_MEMSHARED = 0x00000040,
+ VMSTATMASK_GUEST_MEMCACHE = 0x00000080,
+ VMSTATMASK_GUEST_PAGETOTAL = 0x00000100,
+ VMSTATMASK_VMM_ALLOC = 0x00010000,
+ VMSTATMASK_VMM_FREE = 0x00020000,
+ VMSTATMASK_VMM_BALOON = 0x00040000,
+ VMSTATMASK_VMM_SHARED = 0x00080000,
+ VMSTATMASK_NET_RX = 0x01000000,
+ VMSTATMASK_NET_TX = 0x02000000
+ } VMSTATMASK;
+
+ const ULONG VMSTATS_GUEST_CPULOAD =
+ VMSTATMASK_GUEST_CPUUSER | VMSTATMASK_GUEST_CPUKERNEL |
+ VMSTATMASK_GUEST_CPUIDLE;
+ const ULONG VMSTATS_GUEST_RAMUSAGE =
+ VMSTATMASK_GUEST_MEMTOTAL | VMSTATMASK_GUEST_MEMFREE |
+ VMSTATMASK_GUEST_MEMBALLOON | VMSTATMASK_GUEST_MEMSHARED |
+ VMSTATMASK_GUEST_MEMCACHE | VMSTATMASK_GUEST_PAGETOTAL;
+ const ULONG VMSTATS_VMM_RAM =
+ VMSTATMASK_VMM_ALLOC | VMSTATMASK_VMM_FREE|
+ VMSTATMASK_VMM_BALOON | VMSTATMASK_VMM_SHARED;
+ const ULONG VMSTATS_NET_RATE =
+ VMSTATMASK_NET_RX | VMSTATMASK_NET_TX;
+ const ULONG VMSTATS_ALL =
+ VMSTATS_GUEST_CPULOAD | VMSTATS_GUEST_RAMUSAGE |
+ VMSTATS_VMM_RAM | VMSTATS_NET_RATE;
+ class CollectorGuest;
+
+ class CollectorGuestRequest
+ {
+ public:
+ CollectorGuestRequest()
+ : mCGuest(0) {};
+ virtual ~CollectorGuestRequest() {};
+ void setGuest(CollectorGuest *aGuest) { mCGuest = aGuest; };
+ CollectorGuest *getGuest() { return mCGuest; };
+ virtual HRESULT execute() = 0;
+
+ virtual void debugPrint(void *aObject, const char *aFunction, const char *aText) = 0;
+ protected:
+ CollectorGuest *mCGuest;
+ const char *mDebugName;
+ };
+
+ class CGRQEnable : public CollectorGuestRequest
+ {
+ public:
+ CGRQEnable(ULONG aMask)
+ : mMask(aMask) {};
+ HRESULT execute();
+
+ void debugPrint(void *aObject, const char *aFunction, const char *aText);
+ private:
+ ULONG mMask;
+ };
+
+ class CGRQDisable : public CollectorGuestRequest
+ {
+ public:
+ CGRQDisable(ULONG aMask)
+ : mMask(aMask) {};
+ HRESULT execute();
+
+ void debugPrint(void *aObject, const char *aFunction, const char *aText);
+ private:
+ ULONG mMask;
+ };
+
+ class CGRQAbort : public CollectorGuestRequest
+ {
+ public:
+ CGRQAbort() {};
+ HRESULT execute();
+
+ void debugPrint(void *aObject, const char *aFunction, const char *aText);
+ };
+
+ class CollectorGuestQueue
+ {
+ public:
+ CollectorGuestQueue();
+ ~CollectorGuestQueue();
+ void push(CollectorGuestRequest* rq);
+ CollectorGuestRequest* pop();
+ private:
+ RTCLockMtx mLockMtx;
+ RTSEMEVENT mEvent;
+ std::queue<CollectorGuestRequest*> mQueue;
+ };
+
+ class CollectorGuestManager;
+
+ class CollectorGuest
+ {
+ public:
+ CollectorGuest(Machine *machine, RTPROCESS process);
+ ~CollectorGuest();
+
+ void setManager(CollectorGuestManager *aManager)
+ { mManager = aManager; };
+ bool isUnregistered() { return mUnregistered; };
+ bool isEnabled() { return mEnabled != 0; };
+ bool isValid(ULONG mask) { return (mValid & mask) == mask; };
+ void invalidate(ULONG mask) { mValid &= ~mask; };
+ void unregister() { mUnregistered = true; };
+ void updateStats(ULONG aValidStats, ULONG aCpuUser,
+ ULONG aCpuKernel, ULONG aCpuIdle,
+ ULONG aMemTotal, ULONG aMemFree,
+ ULONG aMemBalloon, ULONG aMemShared,
+ ULONG aMemCache, ULONG aPageTotal,
+ ULONG aAllocVMM, ULONG aFreeVMM,
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx);
+ HRESULT enable(ULONG mask);
+ HRESULT disable(ULONG mask);
+
+ HRESULT enqueueRequest(CollectorGuestRequest *aRequest);
+ HRESULT enableInternal(ULONG mask);
+ HRESULT disableInternal(ULONG mask);
+
+ const com::Utf8Str& getVMName() const { return mMachineName; };
+
+ RTPROCESS getProcess() { return mProcess; };
+ ULONG getCpuUser() { return mCpuUser; };
+ ULONG getCpuKernel() { return mCpuKernel; };
+ ULONG getCpuIdle() { return mCpuIdle; };
+ ULONG getMemTotal() { return mMemTotal; };
+ ULONG getMemFree() { return mMemFree; };
+ ULONG getMemBalloon() { return mMemBalloon; };
+ ULONG getMemShared() { return mMemShared; };
+ ULONG getMemCache() { return mMemCache; };
+ ULONG getPageTotal() { return mPageTotal; };
+ ULONG getAllocVMM() { return mAllocVMM; };
+ ULONG getFreeVMM() { return mFreeVMM; };
+ ULONG getBalloonedVMM() { return mBalloonedVMM; };
+ ULONG getSharedVMM() { return mSharedVMM; };
+ ULONG getVmNetRx() { return mVmNetRx; };
+ ULONG getVmNetTx() { return mVmNetTx; };
+
+ private:
+ HRESULT enableVMMStats(bool mCollectVMMStats);
+
+ CollectorGuestManager *mManager;
+
+ bool mUnregistered;
+ ULONG mEnabled;
+ ULONG mValid;
+ Machine *mMachine;
+ com::Utf8Str mMachineName;
+ RTPROCESS mProcess;
+ ComPtr<IConsole> mConsole;
+ ComPtr<IGuest> mGuest;
+ ULONG mCpuUser;
+ ULONG mCpuKernel;
+ ULONG mCpuIdle;
+ ULONG mMemTotal;
+ ULONG mMemFree;
+ ULONG mMemBalloon;
+ ULONG mMemShared;
+ ULONG mMemCache;
+ ULONG mPageTotal;
+ ULONG mAllocVMM;
+ ULONG mFreeVMM;
+ ULONG mBalloonedVMM;
+ ULONG mSharedVMM;
+ ULONG mVmNetRx;
+ ULONG mVmNetTx;
+ };
+
+ typedef std::list<CollectorGuest*> CollectorGuestList;
+ class CollectorGuestManager
+ {
+ public:
+ CollectorGuestManager();
+ ~CollectorGuestManager();
+ void registerGuest(CollectorGuest* pGuest);
+ void unregisterGuest(CollectorGuest* pGuest);
+ CollectorGuest *getVMMStatsProvider() { return mVMMStatsProvider; };
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void destroyUnregistered();
+ HRESULT enqueueRequest(CollectorGuestRequest *aRequest);
+
+ CollectorGuest *getBlockedGuest() { return mGuestBeingCalled; };
+
+ static DECLCALLBACK(int) requestProcessingThread(RTTHREAD aThread, void *pvUser);
+ private:
+ RTTHREAD mThread;
+ CollectorGuestList mGuests;
+ CollectorGuest *mVMMStatsProvider;
+ CollectorGuestQueue mQueue;
+ CollectorGuest *mGuestBeingCalled;
+ };
+
+ /* Collector Hardware Abstraction Layer *********************************/
+ typedef std::list<RTCString> DiskList;
+
+ class CollectorHAL
+ {
+ public:
+ CollectorHAL() {};
+ virtual ~CollectorHAL() { };
+ virtual int preCollect(const CollectorHints& /* hints */, uint64_t /* iTick */) { return VINF_SUCCESS; }
+ /** Returns averaged CPU usage in 1/1000th per cent across all host's CPUs. */
+ virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
+ /** Returns the average frequency in MHz across all host's CPUs. */
+ virtual int getHostCpuMHz(ULONG *mhz);
+ /** Returns the amount of physical memory in kilobytes. */
+ virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
+ /** Returns file system counters in megabytes. */
+ virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
+ /** Returns disk size in bytes. */
+ virtual int getHostDiskSize(const char *name, uint64_t *size);
+ /** Returns CPU usage in 1/1000th per cent by a particular process. */
+ virtual int getProcessCpuLoad(RTPROCESS process, ULONG *user, ULONG *kernel);
+ /** Returns the amount of memory used by a process in kilobytes. */
+ virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
+
+ /** Returns CPU usage counters in platform-specific units. */
+ virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
+ /** Returns received and transmitted bytes. */
+ virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
+ /** Returns disk usage counters in platform-specific units. */
+ virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
+ /** Returns process' CPU usage counter in platform-specific units. */
+ virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
+
+ /** Returns the lists of disks (aggregate and physical) used by the specified file system. */
+ virtual int getDiskListByFs(const char *name, DiskList& listUsage, DiskList& listLoad);
+ };
+
+ extern CollectorHAL *createHAL();
+
+ /* Base Metrics *********************************************************/
+ class BaseMetric
+ {
+ public:
+ BaseMetric(CollectorHAL *hal, const com::Utf8Str name, ComPtr<IUnknown> object)
+ : mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object),
+ mLastSampleTaken(0), mEnabled(false), mUnregistered(false) {};
+ virtual ~BaseMetric() {};
+
+ virtual void init(ULONG period, ULONG length) = 0;
+ virtual void preCollect(CollectorHints& hints, uint64_t iTick) = 0;
+ virtual void collect() = 0;
+ virtual const char *getUnit() = 0;
+ virtual ULONG getMinValue() = 0;
+ virtual ULONG getMaxValue() = 0;
+ virtual ULONG getScale() = 0;
+
+ bool collectorBeat(uint64_t nowAt);
+
+ virtual HRESULT enable() { mEnabled = true; return S_OK; };
+ virtual HRESULT disable() { mEnabled = false; return S_OK; };
+ void unregister() { mUnregistered = true; };
+
+ bool isUnregistered() { return mUnregistered; };
+ bool isEnabled() { return mEnabled; };
+ ULONG getPeriod() { return mPeriod; };
+ ULONG getLength() { return mLength; };
+ const char *getName() { return mName.c_str(); };
+ ComPtr<IUnknown> getObject() { return mObject; };
+ bool associatedWith(ComPtr<IUnknown> object) { return mObject == object; };
+
+ protected:
+ ULONG mPeriod;
+ ULONG mLength;
+ CollectorHAL *mHAL;
+ const com::Utf8Str mName;
+ ComPtr<IUnknown> mObject;
+ uint64_t mLastSampleTaken;
+ bool mEnabled;
+ bool mUnregistered;
+ };
+
+ class BaseGuestMetric : public BaseMetric
+ {
+ public:
+ BaseGuestMetric(CollectorGuest *cguest, const char *name, ComPtr<IUnknown> object)
+ : BaseMetric(NULL, name, object), mCGuest(cguest) {};
+ protected:
+ CollectorGuest *mCGuest;
+ };
+
+ class HostCpuLoad : public BaseMetric
+ {
+ public:
+ HostCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
+ : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {};
+ ~HostCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
+
+ void init(ULONG period, ULONG length);
+
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
+
+ protected:
+ SubMetric *mUser;
+ SubMetric *mKernel;
+ SubMetric *mIdle;
+ };
+
+ class HostCpuLoadRaw : public HostCpuLoad
+ {
+ public:
+ HostCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
+ : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {};
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ private:
+ uint64_t mUserPrev;
+ uint64_t mKernelPrev;
+ uint64_t mIdlePrev;
+ };
+
+ class HostCpuMhz : public BaseMetric
+ {
+ public:
+ HostCpuMhz(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *mhz)
+ : BaseMetric(hal, "CPU/MHz", object), mMHz(mhz) {};
+ ~HostCpuMhz() { delete mMHz; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {}
+ void collect();
+ const char *getUnit() { return "MHz"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ SubMetric *mMHz;
+ };
+
+ class HostRamUsage : public BaseMetric
+ {
+ public:
+ HostRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available)
+ : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mUsed(used), mAvailable(available) {};
+ ~HostRamUsage() { delete mTotal; delete mUsed; delete mAvailable; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "kB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ SubMetric *mTotal;
+ SubMetric *mUsed;
+ SubMetric *mAvailable;
+ };
+
+ class HostNetworkSpeed : public BaseMetric
+ {
+ public:
+ HostNetworkSpeed(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str shortname, com::Utf8Str /* ifname */, uint32_t speed, SubMetric *linkspeed)
+ : BaseMetric(hal, name, object), mShortName(shortname), mSpeed(speed), mLinkSpeed(linkspeed) {};
+ ~HostNetworkSpeed() { delete mLinkSpeed; };
+
+ void init(ULONG period, ULONG length);
+
+ void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {};
+ void collect() { if (mSpeed) mLinkSpeed->put(mSpeed); };
+ const char *getUnit() { return "mbit/s"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ com::Utf8Str mShortName;
+ uint32_t mSpeed;
+ SubMetric *mLinkSpeed;
+ };
+
+ class HostNetworkLoadRaw : public BaseMetric
+ {
+ public:
+ HostNetworkLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str shortname, com::Utf8Str ifname, uint32_t speed, SubMetric *rx, SubMetric *tx)
+ : BaseMetric(hal, name, object), mShortName(shortname), mInterfaceName(ifname), mRx(rx), mTx(tx), mRxPrev(0), mTxPrev(0), mRc(VINF_SUCCESS) { mSpeed = (uint64_t)speed * (1000000/8); /* Convert to bytes/sec */ };
+ ~HostNetworkLoadRaw() { delete mRx; delete mTx; };
+
+ void init(ULONG period, ULONG length);
+
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_NETWORK_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_NETWORK_LOAD_MULTIPLIER / 100; }
+
+ private:
+ com::Utf8Str mShortName;
+ com::Utf8Str mInterfaceName;
+ SubMetric *mRx;
+ SubMetric *mTx;
+ uint64_t mRxPrev;
+ uint64_t mTxPrev;
+ uint64_t mSpeed;
+ int mRc;
+ };
+
+ class HostFilesystemUsage : public BaseMetric
+ {
+ public:
+ HostFilesystemUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str fsname, SubMetric *total, SubMetric *used, SubMetric *available)
+ : BaseMetric(hal, name, object), mFsName(fsname), mTotal(total), mUsed(used), mAvailable(available) {};
+ ~HostFilesystemUsage() { delete mTotal; delete mUsed; delete mAvailable; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "MB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ com::Utf8Str mFsName;
+ SubMetric *mTotal;
+ SubMetric *mUsed;
+ SubMetric *mAvailable;
+ };
+
+ class HostDiskUsage : public BaseMetric
+ {
+ public:
+ HostDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *total)
+ : BaseMetric(hal, name, object), mDiskName(diskname), mTotal(total) {};
+ ~HostDiskUsage() { delete mTotal; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "MB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ com::Utf8Str mDiskName;
+ SubMetric *mTotal;
+ };
+
+ class HostDiskLoadRaw : public BaseMetric
+ {
+ public:
+ HostDiskLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *util)
+ : BaseMetric(hal, name, object), mDiskName(diskname), mUtil(util), mDiskPrev(0), mTotalPrev(0) {};
+ ~HostDiskLoadRaw() { delete mUtil; };
+
+ void init(ULONG period, ULONG length);
+
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_DISK_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_DISK_LOAD_MULTIPLIER / 100; }
+
+ private:
+ com::Utf8Str mDiskName;
+ SubMetric *mUtil;
+ uint64_t mDiskPrev;
+ uint64_t mTotalPrev;
+ };
+
+
+#ifndef VBOX_COLLECTOR_TEST_CASE
+ class HostRamVmm : public BaseMetric
+ {
+ public:
+ HostRamVmm(CollectorGuestManager *gm, ComPtr<IUnknown> object, SubMetric *allocVMM, SubMetric *freeVMM, SubMetric *balloonVMM, SubMetric *sharedVMM)
+ : BaseMetric(NULL, "RAM/VMM", object), mCollectorGuestManager(gm),
+ mAllocVMM(allocVMM), mFreeVMM(freeVMM), mBalloonVMM(balloonVMM), mSharedVMM(sharedVMM),
+ mAllocCurrent(0), mFreeCurrent(0), mBalloonedCurrent(0), mSharedCurrent(0) {};
+ ~HostRamVmm() { delete mAllocVMM; delete mFreeVMM; delete mBalloonVMM; delete mSharedVMM; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ HRESULT enable();
+ HRESULT disable();
+ const char *getUnit() { return "kB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+
+ private:
+ CollectorGuestManager *mCollectorGuestManager;
+ SubMetric *mAllocVMM;
+ SubMetric *mFreeVMM;
+ SubMetric *mBalloonVMM;
+ SubMetric *mSharedVMM;
+ ULONG mAllocCurrent;
+ ULONG mFreeCurrent;
+ ULONG mBalloonedCurrent;
+ ULONG mSharedCurrent;
+ };
+#endif /* VBOX_COLLECTOR_TEST_CASE */
+
+ class MachineCpuLoad : public BaseMetric
+ {
+ public:
+ MachineCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
+ : BaseMetric(hal, "CPU/Load", object), mProcess(process), mUser(user), mKernel(kernel) {};
+ ~MachineCpuLoad() { delete mUser; delete mKernel; };
+
+ void init(ULONG period, ULONG length);
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
+ protected:
+ RTPROCESS mProcess;
+ SubMetric *mUser;
+ SubMetric *mKernel;
+ };
+
+ class MachineCpuLoadRaw : public MachineCpuLoad
+ {
+ public:
+ MachineCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
+ : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {};
+
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ private:
+ uint64_t mHostTotalPrev;
+ uint64_t mProcessUserPrev;
+ uint64_t mProcessKernelPrev;
+ };
+
+ class MachineRamUsage : public BaseMetric
+ {
+ public:
+ MachineRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
+ : BaseMetric(hal, "RAM/Usage", object), mProcess(process), mUsed(used) {};
+ ~MachineRamUsage() { delete mUsed; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "kB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ RTPROCESS mProcess;
+ SubMetric *mUsed;
+ };
+
+
+#ifndef VBOX_COLLECTOR_TEST_CASE
+ typedef std::list<ComObjPtr<Medium> > MediaList;
+ class MachineDiskUsage : public BaseMetric
+ {
+ public:
+ MachineDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, MediaList &disks, SubMetric *used)
+ : BaseMetric(hal, "Disk/Usage", object), mDisks(disks), mUsed(used) {};
+ ~MachineDiskUsage() { delete mUsed; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "MB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ MediaList mDisks;
+ SubMetric *mUsed;
+ };
+
+ /*
+ * Although MachineNetRate is measured for VM, not for the guest, it is
+ * derived from BaseGuestMetric since it uses the same mechanism for
+ * data collection -- values get pushed by Guest class along with other
+ * guest statistics.
+ */
+ class MachineNetRate : public BaseGuestMetric
+ {
+ public:
+ MachineNetRate(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *rx, SubMetric *tx)
+ : BaseGuestMetric(cguest, "Net/Rate", object), mRx(rx), mTx(tx) {};
+ ~MachineNetRate() { delete mRx; delete mTx; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ HRESULT enable();
+ HRESULT disable();
+ const char *getUnit() { return "B/s"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ SubMetric *mRx, *mTx;
+ };
+
+ class GuestCpuLoad : public BaseGuestMetric
+ {
+ public:
+ GuestCpuLoad(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
+ : BaseGuestMetric(cguest, "Guest/CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {};
+ ~GuestCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ HRESULT enable();
+ HRESULT disable();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; }
+ protected:
+ SubMetric *mUser;
+ SubMetric *mKernel;
+ SubMetric *mIdle;
+ };
+
+ class GuestRamUsage : public BaseGuestMetric
+ {
+ public:
+ GuestRamUsage(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *total, SubMetric *free, SubMetric *balloon, SubMetric *shared, SubMetric *cache, SubMetric *pagedtotal)
+ : BaseGuestMetric(cguest, "Guest/RAM/Usage", object), mTotal(total), mFree(free), mBallooned(balloon), mCache(cache), mPagedTotal(pagedtotal), mShared(shared) {};
+ ~GuestRamUsage() { delete mTotal; delete mFree; delete mBallooned; delete mShared; delete mCache; delete mPagedTotal; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ HRESULT enable();
+ HRESULT disable();
+ const char *getUnit() { return "kB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ SubMetric *mTotal, *mFree, *mBallooned, *mCache, *mPagedTotal, *mShared;
+ };
+#endif /* VBOX_COLLECTOR_TEST_CASE */
+
+ /* Aggregate Functions **************************************************/
+ class Aggregate
+ {
+ public:
+ virtual ULONG compute(ULONG *data, ULONG length) = 0;
+ virtual const char *getName() = 0;
+ virtual ~Aggregate() {}
+ };
+
+ class AggregateAvg : public Aggregate
+ {
+ public:
+ virtual ULONG compute(ULONG *data, ULONG length);
+ virtual const char *getName();
+ };
+
+ class AggregateMin : public Aggregate
+ {
+ public:
+ virtual ULONG compute(ULONG *data, ULONG length);
+ virtual const char *getName();
+ };
+
+ class AggregateMax : public Aggregate
+ {
+ public:
+ virtual ULONG compute(ULONG *data, ULONG length);
+ virtual const char *getName();
+ };
+
+ /* Metric Class *********************************************************/
+ class Metric
+ {
+ public:
+ Metric(BaseMetric *baseMetric, SubMetric *subMetric, Aggregate *aggregate) :
+ mName(subMetric->getName()), mBaseMetric(baseMetric), mSubMetric(subMetric), mAggregate(aggregate)
+ {
+ if (mAggregate)
+ {
+ mName.append(":");
+ mName.append(mAggregate->getName());
+ }
+ }
+
+ ~Metric()
+ {
+ delete mAggregate;
+ }
+ bool associatedWith(ComPtr<IUnknown> object) { return getObject() == object; };
+
+ const char *getName() { return mName.c_str(); };
+ ComPtr<IUnknown> getObject() { return mBaseMetric->getObject(); };
+ const char *getDescription()
+ { return mAggregate ? "" : mSubMetric->getDescription(); };
+ const char *getUnit() { return mBaseMetric->getUnit(); };
+ ULONG getMinValue() { return mBaseMetric->getMinValue(); };
+ ULONG getMaxValue() { return mBaseMetric->getMaxValue(); };
+ ULONG getPeriod() { return mBaseMetric->getPeriod(); };
+ ULONG getLength()
+ { return mAggregate ? 1 : mBaseMetric->getLength(); };
+ ULONG getScale() { return mBaseMetric->getScale(); }
+ void query(ULONG **data, ULONG *count, ULONG *sequenceNumber);
+
+ private:
+ RTCString mName;
+ BaseMetric *mBaseMetric;
+ SubMetric *mSubMetric;
+ Aggregate *mAggregate;
+ };
+
+ /* Filter Class *********************************************************/
+
+ class Filter
+ {
+ public:
+ Filter(const std::vector<com::Utf8Str> &metricNames,
+ const std::vector<ComPtr<IUnknown> > &objects);
+ Filter(const com::Utf8Str &name, const ComPtr<IUnknown> &aObject);
+ static bool patternMatch(const char *pszPat, const char *pszName,
+ bool fSeenColon = false);
+ bool match(const ComPtr<IUnknown> object, const RTCString &name) const;
+ private:
+ typedef std::pair<const ComPtr<IUnknown>, const RTCString> FilterElement;
+ typedef std::list<FilterElement> ElementList;
+
+ ElementList mElements;
+
+ void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object);
+ };
+}
+#endif /* !MAIN_INCLUDED_Performance_h */
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */