Index: /trunk/src/VBox/Main/HostImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/HostImpl.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/HostImpl.cpp	(revision 12400)
@@ -2879,5 +2879,5 @@
 void Host::registerMetrics (PerformanceCollector *aCollector)
 {
-    pm::MetricFactory *metricFactory = aCollector->getMetricFactory();
+    pm::CollectorHAL *hal = aCollector->getHAL();
     /* Create sub metrics */
     pm::SubMetric *cpuLoadUser   = new pm::SubMetric ("CPU/Load/User",
@@ -2899,13 +2899,10 @@
     ComObjPtr <Host> tmp = this;
     tmp.queryInterfaceTo (&objptr);
-    pm::BaseMetric *cpuLoad =
-        metricFactory->createHostCpuLoad (objptr, cpuLoadUser, cpuLoadKernel,
+    pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw (hal, objptr, cpuLoadUser, cpuLoadKernel,
                                           cpuLoadIdle);
     aCollector->registerBaseMetric (cpuLoad);
-    pm::BaseMetric *cpuMhz =
-        metricFactory->createHostCpuMHz (objptr, cpuMhzSM);
+    pm::BaseMetric *cpuMhz = new pm::HostCpuMhz (hal, objptr, cpuMhzSM);
     aCollector->registerBaseMetric (cpuMhz);
-    pm::BaseMetric *ramUsage =
-        metricFactory->createHostRamUsage (objptr, ramUsageTotal, ramUsageUsed,
+    pm::BaseMetric *ramUsage = new pm::HostRamUsage (hal, objptr, ramUsageTotal, ramUsageUsed,
                                            ramUsageFree);
     aCollector->registerBaseMetric (ramUsage);
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 12400)
@@ -7612,5 +7612,5 @@
 void Machine::registerMetrics (PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid)
 {
-    pm::MetricFactory *metricFactory = aCollector->getMetricFactory();
+    pm::CollectorHAL *hal = aCollector->getHAL();
     /* Create sub metrics */
     pm::SubMetric *cpuLoadUser = new pm::SubMetric ("CPU/Load/User",
@@ -7625,10 +7625,9 @@
     ComObjPtr<Machine> tmp = aMachine;
     tmp.queryInterfaceTo (&objptr);
-    pm::BaseMetric *cpuLoad =
-        metricFactory->createMachineCpuLoad (objptr, pid,
+    pm::BaseMetric *cpuLoad = new pm::MachineCpuLoadRaw (hal, objptr, pid,
                                              cpuLoadUser, cpuLoadKernel);
     aCollector->registerBaseMetric (cpuLoad);
-    pm::BaseMetric *ramUsage =
-        metricFactory->createMachineRamUsage (objptr, pid, ramUsageUsed);
+    pm::BaseMetric *ramUsage = new pm::MachineRamUsage (hal, objptr, pid,
+                                                           ramUsageUsed);
     aCollector->registerBaseMetric (ramUsage);
 
Index: /trunk/src/VBox/Main/Performance.cpp
===================================================================
--- /trunk/src/VBox/Main/Performance.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/Performance.cpp	(revision 12400)
@@ -36,36 +36,10 @@
 #include <iprt/cpuset.h>
 
+#include <algorithm>
+
 #include "Logging.h"
 #include "Performance.h"
 
 using namespace pm;
-
-// Default factory
-
-BaseMetric *MetricFactory::createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
-{
-    Assert(mHAL);
-    return new HostCpuLoadRaw(mHAL, object, user, kernel, idle);
-}
-BaseMetric *MetricFactory::createHostCpuMHz(ComPtr<IUnknown> object, SubMetric *mhz)
-{
-    Assert(mHAL);
-    return new HostCpuMhz(mHAL, object, mhz);
-}
-BaseMetric *MetricFactory::createHostRamUsage(ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available)
-{
-    Assert(mHAL);
-    return new HostRamUsage(mHAL, object, total, used, available);
-}
-BaseMetric *MetricFactory::createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
-{
-    Assert(mHAL);
-    return new MachineCpuLoadRaw(mHAL, object, process, user, kernel);
-}
-BaseMetric *MetricFactory::createMachineRamUsage(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
-{
-    Assert(mHAL);
-    return new MachineRamUsage(mHAL, object, process, used);
-}
 
 // Stubs for non-pure virtual methods
@@ -126,5 +100,5 @@
 }
 
-void BaseMetric::collectorBeat(uint64_t nowAt)
+bool BaseMetric::collectorBeat(uint64_t nowAt)
 {
     if (isEnabled())
@@ -135,7 +109,8 @@
             Log4(("{%p} " LOG_FN_FMT ": Collecting %s for obj(%p)...\n",
                         this, __PRETTY_FUNCTION__, getName(), (void *)mObject));
-            collect();
-        }
-    }
+            return true;
+        }
+    }
+    return false;
 }
 
@@ -165,4 +140,9 @@
         mIdle->put(idle);
     }
+}
+
+void HostCpuLoadRaw::preCollect(CollectorHints& hints)
+{
+    hints.collectHostCpuLoad();
 }
 
@@ -226,4 +206,9 @@
 }
 
+void HostRamUsage::preCollect(CollectorHints& hints)
+{
+    hints.collectHostRamUsage();
+}
+
 void HostRamUsage::collect()
 {
@@ -259,4 +244,9 @@
 }
 
+void MachineCpuLoadRaw::preCollect(CollectorHints& hints)
+{
+    hints.collectProcessCpuLoad(mProcess);
+}
+
 void MachineCpuLoadRaw::collect()
 {
@@ -289,4 +279,9 @@
     mLength = length;
     mUsed->init(mLength);
+}
+
+void MachineRamUsage::preCollect(CollectorHints& hints)
+{
+    hints.collectProcessRamUsage(mProcess);
 }
 
Index: /trunk/src/VBox/Main/PerformanceImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/PerformanceImpl.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/PerformanceImpl.cpp	(revision 12400)
@@ -108,20 +108,5 @@
     HRESULT rc = S_OK;
 
-    /* @todo Obviously other platforms must be added as well. */
-#ifdef RT_OS_SOLARIS
-    m.factory = new pm::MetricFactorySolaris();
-#endif
-#ifdef RT_OS_LINUX
-    m.factory = new pm::MetricFactoryLinux();
-#endif
-#ifdef RT_OS_WINDOWS
-    m.factory = new pm::MetricFactoryWin();
-#endif
-#ifdef RT_OS_OS2
-    m.factory = new pm::MetricFactoryOS2();
-#endif
-#ifdef RT_OS_DARWIN
-    m.factory = new pm::MetricFactoryDarwin();
-#endif
+    m.hal = pm::createHAL();
 
     /* Let the sampler know it gets a valid collector.  */
@@ -170,6 +155,9 @@
     m.sampler = NULL;
 
-    delete m.factory;
-    m.factory = NULL;
+    //delete m.factory;
+    //m.factory = NULL;
+
+    delete m.hal;
+    m.hal = NULL;
 
     LogFlowThisFuncLeave();
@@ -469,8 +457,22 @@
     AutoWriteLock alock (this);
 
+    pm::CollectorHints hints;
     uint64_t timestamp = RTTimeMilliTS();
+    BaseMetricList toBeCollected;
+    BaseMetricList::iterator it;
+    /* Compose the list of metrics being collected at this moment */
+    for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
+        if ((*it)->collectorBeat(timestamp))
+        {
+            (*it)->preCollect(hints);
+            toBeCollected.push_back(*it);
+        }
+
+    /* Let know the platform specific code what is being collected */
+    m.hal->preCollect(hints);
+
+    /* Finally, collect the data */
     std::for_each (m.baseMetrics.begin(), m.baseMetrics.end(),
-                   std::bind2nd (std::mem_fun (&pm::BaseMetric::collectorBeat),
-                                 timestamp));
+                   std::mem_fun (&pm::BaseMetric::collect));
     Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
 }
Index: /trunk/src/VBox/Main/darwin/PerformanceDarwin.cpp
===================================================================
--- /trunk/src/VBox/Main/darwin/PerformanceDarwin.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/darwin/PerformanceDarwin.cpp	(revision 12400)
@@ -74,8 +74,7 @@
 };
 
-MetricFactoryDarwin::MetricFactoryDarwin()
+CollectorHAL *createHAL()
 {
-    mHAL = new CollectorDarwin();
-    Assert(mHAL);
+    return new CollectorDarwin();
 }
 
Index: /trunk/src/VBox/Main/include/Performance.h
===================================================================
--- /trunk/src/VBox/Main/include/Performance.h	(revision 12399)
+++ /trunk/src/VBox/Main/include/Performance.h	(revision 12400)
@@ -26,6 +26,8 @@
 #include <VBox/com/defs.h>
 #include <VBox/com/ptr.h>
+#include <algorithm>
 #include <list>
 #include <string>
+#include <vector>
 
 namespace pm
@@ -65,7 +67,75 @@
 
     /* Collector Hardware Abstraction Layer *********************************/
+    enum {
+        COLLECT_NONE      = 0x0,
+        COLLECT_CPU_LOAD  = 0x1,
+        COLLECT_RAM_USAGE = 0x2
+    };
+    typedef int HintFlags;
+    typedef std::pair<RTPROCESS, HintFlags> ProcessFlagsPair;
+
+    inline bool processEqual(ProcessFlagsPair pair, RTPROCESS process)
+    {
+        return pair.first == process;
+    }
+
+    class CollectorHints
+    {
+        typedef std::list<ProcessFlagsPair> ProcessList;
+
+        HintFlags   mHostFlags;
+        ProcessList mProcesses;
+
+        ProcessFlagsPair& findProcess(RTPROCESS process)
+        {
+            ProcessList::iterator it;
+
+            it = std::find_if(mProcesses.begin(),
+                              mProcesses.end(),
+                              std::bind2nd(std::ptr_fun(processEqual), process));
+
+            if (it != mProcesses.end())
+                return *it;
+
+            /* Not found -- add new */
+            mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE));
+            return mProcesses.back();
+        }
+
+    public:
+        CollectorHints() : mHostFlags(COLLECT_NONE) {}
+        void collectHostCpuLoad() { mHostFlags |= COLLECT_CPU_LOAD; }
+        void collectHostRamUsage() { mHostFlags |= COLLECT_RAM_USAGE; }
+        void collectProcessCpuLoad(RTPROCESS process)
+        {
+            findProcess(process).second |= COLLECT_CPU_LOAD;
+        }
+        void collectProcessRamUsage(RTPROCESS process)
+        {
+            findProcess(process).second |= COLLECT_RAM_USAGE;
+        }
+        bool isHostCpuLoadCollected() { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
+        bool isHostRamUsageCollected() { return (mHostFlags & COLLECT_RAM_USAGE) != 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;
+        }
+        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);
+        }
+    };
+
     class CollectorHAL
     {
     public:
+        virtual int preCollect(const CollectorHints& hints) { return VINF_SUCCESS; }
         virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
         virtual int getHostCpuMHz(ULONG *mhz);
@@ -78,4 +148,6 @@
     };
 
+    extern CollectorHAL *createHAL();
+
     /* Base Metrics *********************************************************/
     class BaseMetric
@@ -86,4 +158,5 @@
 
         virtual void init(ULONG period, ULONG length) = 0;
+        virtual void preCollect(CollectorHints& hints) = 0;
         virtual void collect() = 0;
         virtual const char *getUnit() = 0;
@@ -91,5 +164,5 @@
         virtual ULONG getMaxValue() = 0;
 
-        void collectorBeat(uint64_t nowAt);
+        bool collectorBeat(uint64_t nowAt);
 
         void enable() { mEnabled = true; };
@@ -137,4 +210,5 @@
         : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {};
 
+        void preCollect(CollectorHints& hints);
         void collect();
     private:
@@ -151,4 +225,5 @@
 
         void init(ULONG period, ULONG length);
+        void preCollect(CollectorHints& hints) {}
         void collect();
         const char *getUnit() { return "MHz"; };
@@ -166,4 +241,5 @@
 
         void init(ULONG period, ULONG length);
+        void preCollect(CollectorHints& hints);
         void collect();
         const char *getUnit() { return "kB"; };
@@ -199,4 +275,5 @@
         : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {};
 
+        void preCollect(CollectorHints& hints);
         void collect();
     private:
@@ -213,4 +290,5 @@
 
         void init(ULONG period, ULONG length);
+        void preCollect(CollectorHints& hints);
         void collect();
         const char *getUnit() { return "kB"; };
@@ -290,54 +368,5 @@
     };
 
-    /* Metric Factories *****************************************************/
-    class MetricFactory
-    {
-    public:
-        MetricFactory() : mHAL(0) {};
-        ~MetricFactory() { delete mHAL; };
-
-        virtual BaseMetric   *createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle);
-        virtual BaseMetric   *createHostCpuMHz(ComPtr<IUnknown> object, SubMetric *mhz);
-        virtual BaseMetric   *createHostRamUsage(ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available);
-        virtual BaseMetric   *createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel);
-        virtual BaseMetric   *createMachineRamUsage(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used);
-    protected:
-        CollectorHAL *mHAL;
-    };
-
-    class MetricFactorySolaris : public MetricFactory
-    {
-    public:
-        MetricFactorySolaris();
-        // Nothing else to do here (yet)
-    };
-
-    class MetricFactoryLinux : public MetricFactory
-    {
-    public:
-        MetricFactoryLinux();
-        // Nothing else to do here (yet)
-    };
-
-    class MetricFactoryWin : public MetricFactory
-    {
-    public:
-        MetricFactoryWin();
-        // Nothing else to do here (yet)
-    };
-
-    class MetricFactoryOS2 : public MetricFactory
-    {
-    public:
-        MetricFactoryOS2();
-        // Nothing else to do here (yet)
-    };
-
-    class MetricFactoryDarwin : public MetricFactory
-    {
-    public:
-        MetricFactoryDarwin();
-        // Nothing else to do here (yet)
-    };
+    /* Filter Class *********************************************************/
 
     class Filter
Index: /trunk/src/VBox/Main/include/PerformanceImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/PerformanceImpl.h	(revision 12399)
+++ /trunk/src/VBox/Main/include/PerformanceImpl.h	(revision 12400)
@@ -34,5 +34,5 @@
 
 #include <list>
-#include <set>
+//#include <set>
 
 #include "Performance.h"
@@ -107,66 +107,4 @@
 };
 
-
-#if 0
-class ATL_NO_VTABLE PerformanceData :
-    public VirtualBoxBaseNEXT,
-    public VirtualBoxSupportTranslation <PerformanceData>,
-    public IPerformanceData
-{
-private:
-
-    struct Data
-    {
-        /* Constructor. */
-        Data() { }
-
-        bool operator== (const Data &that) const
-        {
-            return this == &that;
-        }
-    };
-
-public:
-
-    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (PerformanceData)
-
-    DECLARE_NOT_AGGREGATABLE (PerformanceData)
-
-    DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-    BEGIN_COM_MAP(PerformanceData)
-        COM_INTERFACE_ENTRY (ISupportErrorInfo)
-        COM_INTERFACE_ENTRY (IPerformanceData)
-    END_COM_MAP()
-
-    NS_DECL_ISUPPORTS
-
-    DECLARE_EMPTY_CTOR_DTOR (PerformanceData)
-
-    HRESULT FinalConstruct();
-    void FinalRelease();
-
-    // public initializer/uninitializer for internal purposes only
-    HRESULT init (cosnt BSTR aMetricName, IUnknown *anObject,
-                  ULONG *data, ULONG aLength);
-    void uninit();
-
-    // IPerformanceData properties
-    STDMETHOD(COMGETTER(MetricName)) (BSTR *aMetricName);
-    STDMETHOD(COMGETTER(Object)) (IUnknown **anObject);
-    STDMETHOD(COMGETTER(Values)) (ComSafeArrayOut (LONG, values));
-
-    // IPerformanceData methods
-
-    // public methods only for internal purposes
-
-private:
-
-    Bstr mMetricName;
-    IUnknown *mObject;
-    ULONG *mData;
-    ULONG mLength;
-};
-#endif
 
 class ATL_NO_VTABLE PerformanceCollector :
@@ -232,5 +170,5 @@
     // (ensure there is a caller and a read lock before calling them!)
 
-    pm::MetricFactory *getMetricFactory() { return m.factory; };
+    pm::CollectorHAL *getHAL() { return m.hal; };
 
     // for VirtualBoxSupportErrorInfoImpl
@@ -254,10 +192,10 @@
     struct Data
     {
-        Data() : factory(0) {};
+        Data() : hal(0) {};
 
         BaseMetricList     baseMetrics;
         MetricList         metrics;
         RTTIMERLR          sampler;
-        pm::MetricFactory *factory;
+        pm::CollectorHAL  *hal;
     };
 
Index: /trunk/src/VBox/Main/linux/PerformanceLinux.cpp
===================================================================
--- /trunk/src/VBox/Main/linux/PerformanceLinux.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/linux/PerformanceLinux.cpp	(revision 12400)
@@ -43,10 +43,7 @@
 };
 
-// Linux Metric factory
-
-MetricFactoryLinux::MetricFactoryLinux()
+CollectorHAL *createHAL()
 {
-    mHAL = new CollectorLinux();
-    Assert(mHAL);
+    return new CollectorLinux();
 }
 
Index: /trunk/src/VBox/Main/os2/PerformanceOs2.cpp
===================================================================
--- /trunk/src/VBox/Main/os2/PerformanceOs2.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/os2/PerformanceOs2.cpp	(revision 12400)
@@ -37,8 +37,7 @@
 
 
-MetricFactoryOS2::MetricFactoryOS2()
+CollectorHAL *createHAL()
 {
-    mHAL = new CollectorOS2();
-    Assert(mHAL);
+    return new CollectorOS2();
 }
 
Index: /trunk/src/VBox/Main/solaris/PerformanceSolaris.cpp
===================================================================
--- /trunk/src/VBox/Main/solaris/PerformanceSolaris.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/solaris/PerformanceSolaris.cpp	(revision 12400)
@@ -55,10 +55,7 @@
 };
 
-// Solaris Metric factory
-
-MetricFactorySolaris::MetricFactorySolaris()
-{
-    mHAL = new CollectorSolaris();
-    Assert(mHAL);
+CollectorHAL *createHAL()
+{
+    return new CollectorSolaris();
 }
 
Index: /trunk/src/VBox/Main/testcase/tstCollector.cpp
===================================================================
--- /trunk/src/VBox/Main/testcase/tstCollector.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/testcase/tstCollector.cpp	(revision 12400)
@@ -24,4 +24,5 @@
 #include <iprt/runtime.h>
 #include <iprt/stream.h>
+#include <iprt/env.h>
 #include <iprt/err.h>
 #include <iprt/process.h>
@@ -66,5 +67,13 @@
 }
 
-#define CALLS_PER_SECOND(n,fn) \
+#define RUN_TIME_MS        1000
+
+#define N_CALLS(n, fn) \
+    for (int call = 0; call < n; ++call) \
+        rc = collector->fn; \
+    if (RT_FAILURE(rc)) \
+        RTPrintf("tstCollector: "#fn" -> %Vrc\n", rc)
+
+#define CALLS_PER_SECOND(fn) \
     nCalls = 0; \
     start = RTTimeMilliTS(); \
@@ -72,5 +81,5 @@
         rc = collector->fn; \
         ++nCalls; \
-    } while(RTTimeMilliTS() - start < 1000); \
+    } while(RTTimeMilliTS() - start < RUN_TIME_MS); \
     if (RT_FAILURE(rc)) \
     { \
@@ -78,6 +87,75 @@
     } \
     else \
-        RTPrintf("%50s -- %u calls per second\n", #fn, nCalls); \
-    totalTime += n * 1000000 / nCalls
+        RTPrintf("%70s -- %u calls per second\n", #fn, nCalls)
+
+void measurePerformance(pm::CollectorHAL *collector, const char *pszName, int cVMs)
+{
+
+    static const char * const args[] = { pszName, "-child", NULL };
+    pm::CollectorHints hints;
+    std::vector<RTPROCESS> processes;
+
+    hints.collectHostCpuLoad();
+    hints.collectHostRamUsage();
+    /* Start fake VMs */
+    for (int i = 0; i < cVMs; ++i)
+    {
+        RTPROCESS pid;
+        int rc = RTProcCreate(pszName, args, RTENV_DEFAULT, 0, &pid);
+        if (RT_FAILURE(rc))
+        {
+            hints.getProcesses(processes);
+            std::for_each(processes.begin(), processes.end(), std::ptr_fun(RTProcTerminate));
+            RTPrintf("tstCollector: RTProcCreate() -> %Vrc\n", rc);
+            return;
+        }
+        hints.collectProcessCpuLoad(pid);
+        hints.collectProcessRamUsage(pid);
+    }
+
+    hints.getProcesses(processes);
+    RTThreadSleep(30000); // Let children settle for half a minute
+
+    int rc;
+    ULONG tmp;
+    uint64_t tmp64;
+    uint64_t start;
+    unsigned int nCalls;
+    uint32_t totalTime = 0;
+    /* Pre-collect */
+    CALLS_PER_SECOND(preCollect(hints));
+    /* Host CPU load */
+    CALLS_PER_SECOND(getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
+    /* Process CPU load */
+    CALLS_PER_SECOND(getRawProcessCpuLoad(processes[nCalls%cVMs], &tmp64, &tmp64, &tmp64));
+    /* Host CPU speed */
+    CALLS_PER_SECOND(getHostCpuMHz(&tmp));
+    /* Host RAM usage */
+    CALLS_PER_SECOND(getHostMemoryUsage(&tmp, &tmp, &tmp));
+    /* Process RAM usage */
+    CALLS_PER_SECOND(getProcessMemoryUsage(processes[nCalls%cVMs], &tmp));
+
+    start = RTTimeNanoTS();
+
+    for (int times = 0; times < 100; times++)
+    {
+        /* Pre-collect */
+        N_CALLS(1, preCollect(hints));
+        /* Host CPU load */
+        N_CALLS(1, getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
+        /* Host CPU speed */
+        N_CALLS(1, getHostCpuMHz(&tmp));
+        /* Host RAM usage */
+        N_CALLS(1, getHostMemoryUsage(&tmp, &tmp, &tmp));
+        /* Process CPU load */
+        N_CALLS(cVMs, getRawProcessCpuLoad(processes[call], &tmp64, &tmp64, &tmp64));
+        /* Process RAM usage */
+        N_CALLS(cVMs, getProcessMemoryUsage(processes[call], &tmp));
+    }
+    printf("\n%u VMs -- %.2f%% of CPU time\n", cVMs, (RTTimeNanoTS() - start) / 10000000. / times);
+
+    /* Shut down fake VMs */
+    std::for_each(processes.begin(), processes.end(), std::ptr_fun(RTProcTerminate));
+}
 
 int main(int argc, char *argv[])
@@ -91,4 +169,10 @@
     {
         RTPrintf("tstCollector: RTR3Init() -> %d\n", rc);
+        return 1;
+    }
+    if (argc > 1 && !strcmp(argv[1], "-child"))
+    {
+        /* We have spawned ourselves as a child process -- scratch the leg */
+        RTThreadSleep(1000000);
         return 1;
     }
@@ -108,6 +192,4 @@
 #endif
 
-    uint64_t start;
-
     pm::CollectorHAL *collector = createCollector();
     if (!collector)
@@ -116,5 +198,7 @@
         return 1;
     }
-#if 1
+#if 0
+    uint64_t start;
+
     uint64_t hostUserStart, hostKernelStart, hostIdleStart;
     uint64_t hostUserStop, hostKernelStop, hostIdleStop, hostTotal;
@@ -219,21 +303,6 @@
 #endif
     RTPrintf("\ntstCollector: TESTING - Performance\n\n");
-    unsigned nCalls;
-    ULONG tmp;
-    uint64_t tmp64;
-    uint32_t totalTime = 0;
-    RTPROCESS pid = RTProcSelf();
-    /* Host CPU load */
-    CALLS_PER_SECOND(1, getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
-    /* Process CPU load */
-    CALLS_PER_SECOND(100, getRawProcessCpuLoad(pid, &tmp64, &tmp64, &tmp64));
-    /* Host CPU speed */
-    CALLS_PER_SECOND(1, getHostCpuMHz(&tmp));
-    /* Host RAM usage */
-    CALLS_PER_SECOND(1, getHostMemoryUsage(&tmp, &tmp, &tmp));
-    /* Process RAM usage */
-    CALLS_PER_SECOND(100, getProcessMemoryUsage(pid, &tmp));
-    
-    printf("%.2f%% of CPU time\n", totalTime / 10000.);
+
+    measurePerformance(collector, argv[0], 100);
     
     delete collector;
Index: /trunk/src/VBox/Main/win/PerformanceWin.cpp
===================================================================
--- /trunk/src/VBox/Main/win/PerformanceWin.cpp	(revision 12399)
+++ /trunk/src/VBox/Main/win/PerformanceWin.cpp	(revision 12400)
@@ -29,4 +29,6 @@
 #include <iprt/mp.h>
 
+#include <map>
+
 #include "Logging.h"
 #include "Performance.h"
@@ -40,4 +42,5 @@
     ~CollectorWin();
 
+    virtual int preCollect(const CollectorHints& hints);
     virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
     virtual int getHostCpuMHz(ULONG *mhz);
@@ -69,10 +72,21 @@
     long               mProcessCpuLoadTimestampHandle;
     long               mProcessMemoryUsedHandle;
+
+    struct VMProcessStats
+    {
+        uint64_t cpuUser;
+        uint64_t cpuKernel;
+        uint64_t cpuTotal;
+        uint64_t ramUsed;
+    };
+
+    typedef std::map<RTPROCESS, VMProcessStats> VMProcessMap;
+
+    VMProcessMap       mProcessStats;
 };
 
-MetricFactoryWin::MetricFactoryWin()
-{
-    mHAL = new CollectorWin();
-    Assert(mHAL);
+CollectorHAL *createHAL()
+{
+    return new CollectorWin();
 }
 
@@ -265,11 +279,10 @@
 }
 
-int CollectorWin::getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
-{
+int CollectorWin::preCollect(const CollectorHints& hints)
+{
+
+    std::vector<RTPROCESS> processes;
+    hints.getProcesses(processes);
+
     HRESULT hr;
     IWbemObjectAccess       **apEnumAccess = NULL;
@@ -283,4 +296,83 @@
         return VERR_INTERNAL_ERROR;
     }
+
+    int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = VERR_NOT_FOUND;
+
+    for (unsigned i = 0; i < dwNumReturned; i++)
+    {
+        DWORD dwIDProcess;
+
+        if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
+            mProcessPIDHandle,
+            &dwIDProcess)))
+        {
+            Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
+            return VERR_INTERNAL_ERROR;
+        }
+        LogFlowThisFunc (("Matching process %x against the list of machines...\n", dwIDProcess));
+        if (std::find(processes.begin(), processes.end(), dwIDProcess) != processes.end())
+        {
+            VMProcessStats vmStats;
+
+            LogFlowThisFunc (("Match found.\n"));
+            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
+                mProcessCpuLoadUserHandle,
+                &vmStats.cpuUser)))
+            {
+                Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr));
+                    return VERR_INTERNAL_ERROR;
+            }
+            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
+                mProcessCpuLoadKernelHandle,
+                &vmStats.cpuKernel)))
+            {
+                Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr));
+                    return VERR_INTERNAL_ERROR;
+            }
+            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
+                mProcessCpuLoadTimestampHandle,
+                &vmStats.cpuTotal)))
+            {
+                Log (("Failed to read 'Timestamp_Sys100NS' property. HR = %x\n", hr));
+                    return VERR_INTERNAL_ERROR;
+            }
+            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
+                mProcessMemoryUsedHandle,
+                &vmStats.ramUsed)))
+            {
+                Log (("Failed to read 'WorkingSet' property. HR = %x\n", hr));
+                    return VERR_INTERNAL_ERROR;
+            }
+
+            mProcessStats[dwIDProcess] = vmStats;
+            LogFlowThisFunc(("process=%x user=%lu kernel=%lu total=%lu\n", dwIDProcess, vmStats.cpuUser, vmStats.cpuKernel, vmStats.cpuTotal));
+            rc = VINF_SUCCESS;
+        }
+        apEnumAccess[i]->Release();
+        apEnumAccess[i] = NULL;
+    }
+    delete [] apEnumAccess;
+
+    LogFlowThisFuncLeave();
+
+    return rc;
+}
+
+int CollectorWin::getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle)
+{
+    return VERR_NOT_IMPLEMENTED;
+}
+
+int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
+{
+    HRESULT hr;
+    IWbemObjectAccess       **apEnumAccess = NULL;
+    DWORD                   dwNumReturned = 0;
+
+    LogFlowThisFuncEnter();
 
     int rc = getObjects(mEnumProcessor, &apEnumAccess, &dwNumReturned);
@@ -395,126 +487,29 @@
 int CollectorWin::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
 {
-    HRESULT hr;
-    IWbemObjectAccess       **apEnumAccess = NULL;
-    DWORD                   dwNumReturned = 0;
-
-    LogFlowThisFuncEnter();
-
-    if (FAILED (hr = mRefresher->Refresh(0L)))
-    {
-        Log (("Refresher failed. HR = %x\n", hr));
+    VMProcessMap::const_iterator it = mProcessStats.find(process);
+
+    if (it == mProcessStats.end())
+    {
+        Log (("No stats pre-collected for process %x\n", process));
         return VERR_INTERNAL_ERROR;
     }
-
-    int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = VERR_NOT_FOUND;
-
-    for (unsigned i = 0; i < dwNumReturned; i++)
-    {
-        DWORD dwIDProcess;
-
-        if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
-            mProcessPIDHandle,
-            &dwIDProcess)))
-        {
-            Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
-            return VERR_INTERNAL_ERROR;
-        }
-        LogFlowThisFunc (("Matching machine process %x against %x...\n", process, dwIDProcess));
-        if (dwIDProcess == process)
-        {
-            LogFlowThisFunc (("Match found.\n"));
-            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
-                mProcessCpuLoadUserHandle,
-                user)))
-            {
-            Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr));
-                return VERR_INTERNAL_ERROR;
-            }
-            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
-                mProcessCpuLoadKernelHandle,
-                kernel)))
-            {
-            Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr));
-                return VERR_INTERNAL_ERROR;
-            }
-            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
-                mProcessCpuLoadTimestampHandle,
-                total)))
-            {
-            Log (("Failed to read 'Timestamp_Sys100NS' property. HR = %x\n", hr));
-                return VERR_INTERNAL_ERROR;
-            }
-            rc = VINF_SUCCESS;
-        }
-        apEnumAccess[i]->Release();
-        apEnumAccess[i] = NULL;
-    }
-    delete [] apEnumAccess;
-
-    LogFlowThisFunc(("user=%lu kernel=%lu total=%lu\n", *user, *kernel, *total));
-    LogFlowThisFuncLeave();
-
-    return rc;
+    *user   = it->second.cpuUser;
+    *kernel = it->second.cpuKernel;
+    *total  = it->second.cpuTotal;
+    return VINF_SUCCESS;
 }
 
 int CollectorWin::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
 {
-    HRESULT hr;
-    IWbemObjectAccess       **apEnumAccess = NULL;
-    DWORD                   dwNumReturned = 0;
-
-    LogFlowThisFuncEnter();
-
-    if (FAILED (hr = mRefresher->Refresh(0L)))
-    {
-        Log (("Refresher failed. HR = %x\n", hr));
+    VMProcessMap::const_iterator it = mProcessStats.find(process);
+
+    if (it == mProcessStats.end())
+    {
+        Log (("No stats pre-collected for process %x\n", process));
         return VERR_INTERNAL_ERROR;
     }
-
-    int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = VERR_NOT_FOUND;
-
-    for (unsigned i = 0; i < dwNumReturned; i++)
-    {
-        DWORD dwIDProcess;
-
-        if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
-            mProcessPIDHandle,
-            &dwIDProcess)))
-        {
-            Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
-            return VERR_INTERNAL_ERROR;
-        }
-        if (dwIDProcess == process)
-        {
-            uint64_t u64used = 0;
-
-            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
-                mProcessMemoryUsedHandle,
-                &u64used)))
-            {
-            Log (("Failed to read 'WorkingSet' property. HR = %x\n", hr));
-                return VERR_INTERNAL_ERROR;
-            }
-            *used = (ULONG)(u64used / 1024);
-            rc = VINF_SUCCESS;
-        }
-        apEnumAccess[i]->Release();
-        apEnumAccess[i] = NULL;
-    }
-    delete [] apEnumAccess;
-
-    LogFlowThisFunc(("used=%lu\n", *used));
-    LogFlowThisFuncLeave();
-
-    return rc;
-}
-
-}
+    *used = (ULONG)(it->second.ramUsed / 1024);
+    return VINF_SUCCESS;
+}
+
+}
