Index: trunk/src/VBox/Main/HostImpl.cpp
===================================================================
--- trunk/src/VBox/Main/HostImpl.cpp	(revision 10535)
+++ trunk/src/VBox/Main/HostImpl.cpp	(revision 10544)
@@ -171,13 +171,5 @@
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /* Start resource usage sampler */
-    {
-        int vrc = RTTimerCreate (&mUsageSampler, VBOX_USAGE_SAMPLER_INTERVAL,
-                                 UsageSamplerCallback, this);
-        AssertMsgRC (vrc, ("Failed to create resource usage sampling "
-                           "timer (%Rra)\n", vrc));
-        if (RT_FAILURE (vrc))
-            return E_FAIL;
-    }
+    registerMetrics(parent->getCollector());
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
@@ -195,4 +187,8 @@
 
     AssertReturn (isReady(), (void) 0);
+
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+    unregisterMetrics(mParent->getCollector());
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
 #ifdef VBOX_WITH_USB
@@ -211,13 +207,4 @@
     mUSBDeviceFilters.clear();
 #endif
-
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /* Destroy resource usage sampler */
-    {
-        int vrc = RTTimerDestroy (mUsageSampler);
-        AssertMsgRC (vrc, ("Failed to destroy resource usage "
-                           "sampling timer (%Rra)\n", vrc));
-    }
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
     setReady (FALSE);
@@ -1110,20 +1097,4 @@
     return E_NOTIMPL;
 #endif
-}
-
-STDMETHODIMP Host::GetProcessorUsage (ULONG *aUser, ULONG *aSystem, ULONG *aIdle)
-{
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    if (aUser == NULL || aSystem == NULL || aIdle == NULL)
-        return E_POINTER;
-
-    *aUser   = mCpuStats.u32User;
-    *aSystem = mCpuStats.u32System;
-    *aIdle   = mCpuStats.u32Idle;
-
-    return S_OK;
-#else /* !VBOX_WITH_RESOURCE_USAGE_API */
-    return E_NOTIMPL;
-#endif /* !VBOX_WITH_RESOURCE_USAGE_API */
 }
 
@@ -2722,24 +2693,37 @@
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
-
-/* static */
-void Host::UsageSamplerCallback (PRTTIMER pTimer, void *pvUser, uint64_t iTick)
-{
-    AssertReturnVoid (pvUser != NULL);
-    static_cast <Host *> (pvUser)->usageSamplerCallback();
-}
-
-void Host::usageSamplerCallback()
-{
-    int vrc = RTSystemProcessorGetUsageStats (&mCpuStats);
-    AssertMsgRC (vrc, ("Failed to get CPU stats (%Rra)\n", vrc));
-
-//  LogFlowThisFunc (("user=%u%% system=%u%% &mCpuStats=%p\n",
-//                    mCpuStats.u32User / 10000000,
-//                    mCpuStats.u32System / 10000000, &mCpuStats);
-//  LogFlowThisFunc (("user=%.2f system=%.2f idle=%.2f\n", mCpuStats.u32User/10000000.,
-//                    mCpuStats.u32System/10000000., mCpuStats.u32Idle/10000000.);
-}
-
+void Host::registerMetrics(PerformanceCollector *collector)
+{
+    pm::MetricFactory *metricFactory = collector->getMetricFactory();
+    // Create sub metrics
+    pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User");
+    pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel");
+    pm::SubMetric *cpuLoadIdle = new pm::SubMetric("CPU/Load/Idle");
+    // Create and register base metrics
+    IUnknown *objptr;
+    ComObjPtr<Host> tmp = this;
+    tmp.queryInterfaceTo(&objptr);
+    pm::BaseMetric *cpuLoad =
+        metricFactory->createHostCpuLoad(objptr, cpuLoadUser, cpuLoadKernel, cpuLoadIdle);
+    collector->registerBaseMetric(cpuLoad);
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateAvg()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateMin()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateMax()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateAvg()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateMin()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateMax()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, 0));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, new pm::AggregateAvg()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, new pm::AggregateMin()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, new pm::AggregateMax()));
+};
+
+void Host::unregisterMetrics(PerformanceCollector *collector)
+{
+    collector->unregisterMetricsFor(this);
+    collector->unregisterBaseMetricsFor(this);
+};
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
Index: trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/MachineImpl.cpp	(revision 10535)
+++ trunk/src/VBox/Main/MachineImpl.cpp	(revision 10544)
@@ -147,8 +147,4 @@
     mSession.mPid = NIL_RTPROCESS;
     mSession.mState = SessionState_Closed;
-
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    mUsageSampler = NULL;
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 }
 
@@ -501,16 +497,4 @@
     }
 
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /* Start resource usage sampler */
-    {
-        vrc = RTTimerCreate (&mData->mUsageSampler, VBOX_USAGE_SAMPLER_INTERVAL,
-                             Machine::UsageSamplerCallback, this);
-        AssertMsgRC (vrc, ("Failed to create resource usage "
-                            "sampling timer(%Rra)\n", vrc));
-        if (RT_FAILURE (vrc))
-            rc = E_FAIL;
-    }
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
-
     LogFlowThisFunc (("mName='%ls', mRegistered=%RTbool, mAccessible=%RTbool "
                       "rc=%08X\n",
@@ -636,13 +620,4 @@
      */
     AutoMultiWriteLock2 alock (mParent, this);
-
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /* Destroy resource usage sampler */
-    {
-        int vrc = RTTimerDestroy (mData->mUsageSampler);
-        AssertMsgRC (vrc, ("Failed to destroy resource usage "
-                           "sampling timer (%Rra)\n", vrc));
-    }
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
     if (!mData->mSession.mMachine.isNull())
@@ -2814,22 +2789,4 @@
 }
 
-STDMETHODIMP Machine::GetProcessorUsage (ULONG *aUser, ULONG *aSystem)
-{
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    if (aUser == NULL || aSystem == NULL)
-        return E_POINTER;
-
-//  LogFlowThisFunc (("user=%u%% system=%u%% &mData->mCpuStats=%p\n",
-//                    mData->mCpuStats.u32User / 10000000,
-//                    mData->mCpuStats.u32System / 10000000, &mData->mCpuStats));
-
-    *aUser   = mData->mCpuStats.u32User;
-    *aSystem = mData->mCpuStats.u32System;
-    return S_OK;
-#else /* !VBOX_WITH_RESOURCE_USAGE_API */
-    return E_NOTIMPL;
-#endif /* !VBOX_WITH_RESOURCE_USAGE_API */
-}
-
 
 // public methods for internal purposes
@@ -7320,35 +7277,36 @@
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
-
-/* static */
-void Machine::UsageSamplerCallback (PRTTIMER pTimer, void *pvUser, uint64_t iTick)
-{
-    AssertReturnVoid (pvUser != NULL);
-    static_cast <Machine *> (pvUser)->usageSamplerCallback();
-}
-
-void Machine::usageSamplerCallback()
-{
-//  LogFlowThisFunc (("mData->mSession.mPid = %u &mData->mCpuStats = %p)\n",
-//                    mData->mSession.mPid, &m_CpuStats));
-    if (mData->mSession.mPid != NIL_RTPROCESS)
-    {
-        int vrc = RTProcessGetProcessorUsageStats (mData->mSession.mPid,
-                                                   &mData->mCpuStats);
-        AssertMsgRC (vrc, ("Failed to get CPU stats (%Rra)\n", vrc));
-    }
-    else
-    {
-        mData->mCpuStats.u32User   = 0;
-        mData->mCpuStats.u32System = 0;
-    }
-//  LogFlowThisFunc (("user=%u%% system=%u%% &mData->mCpuStats=%p\n",
-//                    mData->mCpuStats.u32User / 10000000,
-//                    mData->mCpuStats.u32System / 10000000, &mData->mCpuStats));
-//  LogFlowThisFunc (("user=%.2f system=%.2f\n",
-//                    mData->mCpuStats.u32User/10000000., mData->mCpuStats.u32System/10000000.));
-}
-
+void Machine::registerMetrics(PerformanceCollector *collector)
+{
+    pm::MetricFactory *metricFactory = collector->getMetricFactory();
+    // Create sub metrics
+    pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User");
+    pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel");
+    // Create and register base metrics
+    IUnknown *objptr;
+
+    ComObjPtr<Machine> tmp = this;
+    tmp.queryInterfaceTo(&objptr);
+    pm::BaseMetric *cpuLoad =
+        metricFactory->createMachineCpuLoad(objptr, mData->mSession.mPid, cpuLoadUser, cpuLoadKernel);
+    collector->registerBaseMetric(cpuLoad);
+
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateAvg()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateMin()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, new pm::AggregateMax()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateAvg()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateMin()));
+    collector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, new pm::AggregateMax()));
+};
+
+void Machine::unregisterMetrics(PerformanceCollector *collector)
+{
+    collector->unregisterMetricsFor(this);
+    collector->unregisterBaseMetricsFor(this);
+};
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
+
 
 /////////////////////////////////////////////////////////////////////////////
@@ -10406,2 +10364,4 @@
     return S_OK;
 }
+
+
Index: trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/Makefile.kmk	(revision 10535)
+++ trunk/src/VBox/Main/Makefile.kmk	(revision 10544)
@@ -259,4 +259,10 @@
 VBoxSVC_SOURCES.solaris += solaris/USBProxyServiceSolaris.cpp
 VBoxSVC_SOURCES.win     +=     win/USBProxyServiceWindows.cpp
+endif
+
+ifdef VBOX_WITH_RESOURCE_USAGE_API
+VBoxSVC_SOURCES  += \
+	PerformanceImpl.cpp \
+	Performance.cpp
 endif
 
Index: trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 10535)
+++ trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 10544)
@@ -228,4 +228,11 @@
             Key global = tree.rootKey().key ("Global");
 
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+            /* create the performance collector object BEFORE host */
+            unconst (mData.mPerformanceCollector).createObject();
+            rc = mData.mPerformanceCollector->init ();
+            ComAssertComRCThrowRC (rc);
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+
             /* create the host object early, machines will need it */
             unconst (mData.mHost).createObject();
@@ -376,4 +383,12 @@
     }
 
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+    if (mData.mPerformanceCollector)
+    {
+        mData.mPerformanceCollector->uninit();
+        unconst (mData.mPerformanceCollector).setNull();
+    }
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+
     /*
      *  Uninit all other children still referenced by clients
@@ -571,4 +586,23 @@
     return S_OK;
 }
+
+STDMETHODIMP
+VirtualBox::COMGETTER(PerformanceCollector) (IPerformanceCollector **aPerformanceCollector)
+{
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+    if (!aPerformanceCollector)
+        return E_POINTER;
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    mData.mPerformanceCollector.queryInterfaceTo (aPerformanceCollector);
+
+    return S_OK;
+#else /* !VBOX_WITH_RESOURCE_USAGE_API */
+    return E_NOTIMPL;
+#endif /* !VBOX_WITH_RESOURCE_USAGE_API */
+}
+
 
 /**
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 10535)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 10544)
@@ -885,5 +885,5 @@
   <interface
     name="IVirtualBox" extends="$dispatched"
-    uuid="2d3b9ea7-25f5-4f07-a8e1-7dd7e0dcf667"
+    uuid="557a07bc-e6ae-4520-a361-4a8493199137"
     wsmap="managed"
   >
@@ -1055,4 +1055,9 @@
           implemented and therefore this collection is always empty.
         </note>
+      </desc>
+    </attribute>
+    <attribute name="performanceCollector" type="IPerformanceCollector" readonly="yes">
+      <desc>
+        The only instance of IPerformanceCollector.
       </desc>
     </attribute>
@@ -3530,26 +3535,4 @@
     </method>
 
-    <method name="getProcessorUsage">
-      <desc>
-        Returns the current processor usage by this virtual machine measured
-        over all cores of all processors in the host system.
-
-        The values returned for each parameter are in range from <tt>0</tt> (the
-        machine is powered off or does not load the CPUs at all) to
-        <tt>1 000 000 000</tt> (all cores of all CPUs are fully in use by this
-        machine).
-      </desc>
-      <param name="user" type="unsigned long" dir="out">
-        <desc>
-          Pecentage of processor time spent executing in user mode.
-        </desc>
-      </param>
-      <param name="system" type="unsigned long" dir="out">
-        <desc>
-          Pecentage of processor time spent executing in kernel mode.
-        </desc>
-      </param>
-    </method>
-
   </interface>
 
@@ -5053,35 +5036,4 @@
     </method>
 
-    <method name="getProcessorUsage">
-      <desc>
-        Returns the processor usage by the whole host system measured over all
-        cores of all processors of the host machine.
-
-        The values returned for each parameter are in range from <tt>0</tt> (the
-        machine is powered off or doesn't load the CPUs at all) to
-        <tt>1 000 000 000</tt> (all cores of all CPUs are fully loaded by this
-        machine).
-
-        <note>
-          The maximum value is 1000000000 which means that all cores of all CPUs
-          are completely used.
-        </note>
-      </desc>
-      <param name="user" type="unsigned long" dir="out">
-        <desc>
-          Pecentage of processor time spent executing in user mode.
-        </desc>
-      </param>
-      <param name="system" type="unsigned long" dir="out">
-        <desc>
-          Pecentage of processor time spent executing in kernel mode.
-        </desc>
-      </param>
-      <param name="idle" type="unsigned long" dir="out">
-        <desc>
-          Pecentage of processor time spent doing nothing.
-        </desc>
-      </param>
-    </method>
   </interface>
 
@@ -10122,4 +10074,148 @@
 </if>
 
+  <interface
+    name="IPerformanceMetric" extends="$unknown"
+    uuid="50831d4c-ed55-4221-836c-87b487d3b44a" wsmap="managed"
+  >
+    <desc>Holds metrics parameters.</desc>
+  
+    <attribute name="metricName" type="wstring" readonly="yes">
+      <desc>
+        Name of the metric.
+      </desc>
+    </attribute>
+
+    <attribute name="object" type="$unknown" readonly="yes">
+      <desc>
+        The object this metric belongs to.
+      </desc>
+    </attribute>
+
+    <attribute name="period" type="unsigned long" readonly="yes">
+      <desc>
+        The time interval between samples, measured in seconds.
+      </desc>
+    </attribute>
+
+    <attribute name="count" type="unsigned long" readonly="yes">
+      <desc>
+        The number of recent samples retained by the collector. Older samples 
+        are discarded.
+      </desc>
+    </attribute>
+
+    <attribute name="unit" type="wstring" readonly="yes">
+      <desc>
+        The unit of measurement.
+      </desc>
+    </attribute>
+
+    <attribute name="minimumValue" type="long" readonly="yes">
+      <desc>
+        The minimum possible value of this metric.
+      </desc>
+    </attribute>
+
+    <attribute name="maximumValue" type="long" readonly="yes">
+      <desc>
+        The maximum possible value of this metric.
+      </desc>
+    </attribute>
+  </interface>
+
+  <interface
+    name="IPerformanceCollector" extends="$unknown"
+    uuid="dcd37e5a-3964-43d1-be30-0f3c7234e347"
+    wsmap="managed"
+  >
+    <desc>
+      This object collects and stores performace metrics data. Performance 
+      metrics are associated with objects like IHost and IMachine. Each object 
+      has a distict set of performance metrics. It can be obtained with
+      <link to="IPerformanceCollector::getMetrics"/>.
+    </desc>
+
+    <attribute name="metricNames" type="wstring" readonly="yes" safearray="yes">
+      <desc>
+        An array of unique names of metrics regardless of objects they are 
+        associated with.
+      </desc>
+    </attribute>
+  
+    <method name="getMetrics">
+      <desc>
+        Returns parameters (characteristics?) of specified metrics for a set of
+        objects.
+        <note>
+          Null metrics array means all metrics. Null object array means all 
+          existing objects.
+        </note>
+      </desc>
+      <param name="metricNames" type="wstring" dir="in" safearray="yes"/>
+      <param name="objects" type="$unknown" dir="in" safearray="yes"/>
+      <param name="metrics" type="IPerformanceMetric" dir="return" safearray="yes"/>
+    </method>
+  
+    <method name="setupMetrics">
+      <desc>
+        Sets parameters of specified metrics for a set of objects.
+        <note>
+          Null metrics array means all metrics. Null object array means all 
+          existing objects.
+        </note>
+      </desc>
+      <param name="metricNames" type="wstring" dir="in" safearray="yes"/>
+      <param name="objects" type="$unknown" dir="in" safearray="yes"/>
+      <param name="period" type="unsigned long" dir="in"/>
+      <param name="count" type="unsigned long" dir="in"/>
+    </method>
+
+    <method name="enableMetrics">
+      <desc>
+        Turn on collection of specified metrics.
+        <note>
+          Null metrics array means all metrics. Null object array means all 
+          existing objects.
+        </note>
+      </desc>
+      <param name="metricNames" type="wstring" dir="in" safearray="yes"/>
+      <param name="objects" type="$unknown" dir="in" safearray="yes"/>
+    </method>
+
+    <method name="disableMetrics">
+      <desc>
+        Turn off collection of specified metrics.
+        <note>
+          Null metrics array means all metrics. Null object array means all 
+          existing objects.
+        </note>
+      </desc>
+      <param name="metricNames" type="wstring" dir="in" safearray="yes"/>
+      <param name="objects" type="$unknown" dir="in" safearray="yes"/>
+    </method>
+
+    <method name="queryMetricsData">
+      <desc>
+        Queries collected metrics data for a set of objects.
+        <note>
+          Null metrics array means all applicable metrics. Null object array 
+          means all existing objects. The @a returnData parameter is a
+          flattened array of arrays. Each start and length of a sub-array is
+          indicated by @a returnDataIndices and @a returnDataLengths. The
+          rationale behind this API style is that it doesn't require objects
+          to be returned, and thus eliminates all but the unavoidable IPC.
+        </note>
+      </desc>
+      <param name="metricNames" type="wstring" dir="in" safearray="yes"/>
+      <param name="objects" type="$unknown" dir="in" safearray="yes"/>
+      <param name="returnMetricNames" type="wstring" dir="out" safearray="yes"/>
+      <param name="returnObjects" type="$unknown" dir="out" safearray="yes"/>
+      <param name="returnDataIndices" type="unsigned long" dir="out" safearray="yes"/>
+      <param name="returnDataLengths" type="unsigned long" dir="out" safearray="yes"/>
+      <param name="returnData" type="long" dir="return" safearray="yes"/>
+    </method>
+
+  </interface>
+
   <module name="VBoxSVC" context="LocalServer">
     <class name="VirtualBox" uuid="B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F"
Index: trunk/src/VBox/Main/include/HostImpl.h
===================================================================
--- trunk/src/VBox/Main/include/HostImpl.h	(revision 10535)
+++ trunk/src/VBox/Main/include/HostImpl.h	(revision 10544)
@@ -36,13 +36,4 @@
 # include "win/svchlp.h"
 #endif
-
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-#include "iprt/timer.h"
-#include "iprt/system.h"
-
-/* Each second we obtain new CPU load stats. */
-#define VBOX_USAGE_SAMPLER_INTERVAL 1000
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
-
 
 class VirtualBox;
@@ -110,6 +101,4 @@
     STDMETHOD(RemoveUSBDeviceFilter) (ULONG aPosition, IHostUSBDeviceFilter **aFilter);
 
-    STDMETHOD(GetProcessorUsage) (ULONG *aUser, ULONG *aSystem, ULONG *aIdle);
-
     // public methods only for internal purposes
 
@@ -171,8 +160,6 @@
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /** Static timer callback. */
-    static void UsageSamplerCallback (PRTTIMER pTimer, void *pvUser, uint64_t iTick);
-    /** Member timer callback. */
-    void usageSamplerCallback();
+    void registerMetrics(PerformanceCollector *collector);
+    void unregisterMetrics(PerformanceCollector *collector);
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
@@ -186,10 +173,4 @@
 #endif /* VBOX_WITH_USB */
 
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /** Pointer to the usage sampling timer. */
-    PRTTIMER mUsageSampler;
-    /** Structure to hold processor usage stats. */
-    RTCPUUSAGESTATS mCpuStats;
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 };
 
Index: trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- trunk/src/VBox/Main/include/MachineImpl.h	(revision 10535)
+++ trunk/src/VBox/Main/include/MachineImpl.h	(revision 10544)
@@ -39,4 +39,7 @@
 #include "BIOSSettingsImpl.h"
 #include "SATAControllerImpl.h"
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+#include "PerformanceImpl.h"
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
 // generated header
@@ -48,8 +51,4 @@
 #include <iprt/thread.h>
 #include <iprt/time.h>
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-#include <iprt/system.h>
-#include <iprt/timer.h>
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
 #include <list>
@@ -169,10 +168,4 @@
         ComObjPtr <Snapshot> mCurrentSnapshot;
 
-#ifdef VBOX_WITH_RESOURCE_USAGE_API
-        /** Pointer to the usage sampling timer. */
-        PRTTIMER mUsageSampler;
-        /** Structure to hold processor usage stats. */
-        RTPROCCPUUSAGESTATS mCpuStats;
-#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     };
 
@@ -530,6 +523,4 @@
     STDMETHOD(SetGuestProperty) (INPTR BSTR aKey, INPTR BSTR aValue);
 
-    STDMETHOD(GetProcessorUsage) (ULONG *user, ULONG *system);
-
     // public methods only for internal purposes
 
@@ -721,8 +712,6 @@
 
 #ifdef VBOX_WITH_RESOURCE_USAGE_API
-    /** Static timer callback. */
-    static void UsageSamplerCallback (PRTTIMER pTimer, void *pvUser, uint64_t iTick);
-    /** Member timer callback. */
-    void usageSamplerCallback();
+    void registerMetrics(PerformanceCollector *collector);
+    void unregisterMetrics(PerformanceCollector *collector);
 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
Index: trunk/src/VBox/Main/include/VirtualBoxImpl.h
===================================================================
--- trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 10535)
+++ trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 10544)
@@ -36,4 +36,9 @@
 # include "win/resource.h"
 #endif
+
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+#include "PerformanceImpl.h"
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+
 
 class Machine;
@@ -127,4 +132,5 @@
     STDMETHOD(COMGETTER(GuestOSTypes)) (IGuestOSTypeCollection **aGuestOSTypes);
     STDMETHOD(COMGETTER(SharedFolders)) (ISharedFolderCollection **aSharedFolders);
+    STDMETHOD(COMGETTER(PerformanceCollector)) (IPerformanceCollector **aPerformanceCollector);
 
     /* IVirtualBox methods */
@@ -345,4 +351,8 @@
     static const wchar_t *getComponentName() { return L"VirtualBox"; }
 
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+    PerformanceCollector *getCollector() { return mData.mPerformanceCollector; };
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+
 private:
 
@@ -414,4 +424,7 @@
         const ComObjPtr <Host> mHost;
         const ComObjPtr <SystemProperties> mSystemProperties;
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+        const ComObjPtr <PerformanceCollector> mPerformanceCollector;
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 
         CfgFile mCfgFile;
Index: trunk/src/VBox/Main/testcase/tstAPI.cpp
===================================================================
--- trunk/src/VBox/Main/testcase/tstAPI.cpp	(revision 10535)
+++ trunk/src/VBox/Main/testcase/tstAPI.cpp	(revision 10544)
@@ -920,16 +920,47 @@
 
 #if 1
-    for (int i = 0; i < 10; i++)
-    {
+    {
+        Bstr metricNames[] = { L"CPU/User:avg,CPU/System:avg,CPU/Idle:avg" };
+        com::SafeArray<BSTR> metrics(1);
+        metricNames[0].detachTo(&metrics[0]);
+
         ComPtr <IHost> host;
         CHECK_RC_BREAK (virtualBox->COMGETTER(Host) (host.asOutParam()));
+        ComPtr <IPerformanceCollector> collector;
+        CHECK_RC( virtualBox->COMGETTER(PerformanceCollector)(collector.asOutParam()) );
+
+        com::SafeIfaceArray<IUnknown> objects(1);
+        host.queryInterfaceTo(&objects[0]);
+        collector->SetupMetrics(ComSafeArrayAsInParam(metrics),
+                                ComSafeArrayAsInParam(objects), 1u, 10u);
+        RTThreadSleep(3000); /* Sleep 10 seconds. */
+        /*com::SafeIfaceArray<IPerformanceData> result;
+        collector->QueryMetricsData(ComSafeArrayAsInParam(metrics),
+                                    ComSafeArrayAsInParam(objects),
+                                    ComSafeArrayAsOutParam(result));
+        for (unsigned i = 0; i < result.size(); i++)
+        {
+            Bstr metricName;
+            result[i]->COMGETTER(MetricName) (metricName.asOutParam());
+            com::SafeArray<LONG> values;
+            result[i]->COMGETTER(Values) (ComSafeArrayAsOutParam(values));
+            printf("%ls", metricName.raw());
+            for (unsigned j = 0; j < values.size(); j++)
+            {
+                printf(" %d\n", values[j]);
+            }
+        }*/
+    }
+#endif
+#if 0
+    for (int i = 0; i < 10; i++)
+    {
         ULONG user, system, idle;
         host->GetProcessorUsage(&user, &system, &idle);
         printf("user=%u system=%u idle=%u\n", user/10000000, system/10000000, idle/10000000);
-        RTThreadSleep(1000);
-    }
-#endif
-
-#if 1
+    }
+#endif
+
+#if 0
     {
         ComPtr <IMachine> machine;
Index: trunk/src/VBox/Main/xpcom/server.cpp
===================================================================
--- trunk/src/VBox/Main/xpcom/server.cpp	(revision 10535)
+++ trunk/src/VBox/Main/xpcom/server.cpp	(revision 10544)
@@ -189,4 +189,10 @@
 NS_DECL_CLASSINFO(SystemProperties)
 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SystemProperties, ISystemProperties)
+#ifdef VBOX_WITH_RESOURCE_USAGE_API
+NS_DECL_CLASSINFO(PerformanceCollector)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(PerformanceCollector, IPerformanceCollector)
+NS_DECL_CLASSINFO(PerformanceMetric)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(PerformanceMetric, IPerformanceMetric)
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
 NS_DECL_CLASSINFO(BIOSSettings)
 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(BIOSSettings, IBIOSSettings)
