VirtualBox

Changeset 12400 in vbox


Ignore:
Timestamp:
Sep 11, 2008 10:34:58 AM (16 years ago)
Author:
vboxsync
Message:

PerfAPI: Improved Win collector. More realistic performance test. No factories.

Location:
trunk/src/VBox/Main
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/HostImpl.cpp

    r12338 r12400  
    28792879void Host::registerMetrics (PerformanceCollector *aCollector)
    28802880{
    2881     pm::MetricFactory *metricFactory = aCollector->getMetricFactory();
     2881    pm::CollectorHAL *hal = aCollector->getHAL();
    28822882    /* Create sub metrics */
    28832883    pm::SubMetric *cpuLoadUser   = new pm::SubMetric ("CPU/Load/User",
     
    28992899    ComObjPtr <Host> tmp = this;
    29002900    tmp.queryInterfaceTo (&objptr);
    2901     pm::BaseMetric *cpuLoad =
    2902         metricFactory->createHostCpuLoad (objptr, cpuLoadUser, cpuLoadKernel,
     2901    pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw (hal, objptr, cpuLoadUser, cpuLoadKernel,
    29032902                                          cpuLoadIdle);
    29042903    aCollector->registerBaseMetric (cpuLoad);
    2905     pm::BaseMetric *cpuMhz =
    2906         metricFactory->createHostCpuMHz (objptr, cpuMhzSM);
     2904    pm::BaseMetric *cpuMhz = new pm::HostCpuMhz (hal, objptr, cpuMhzSM);
    29072905    aCollector->registerBaseMetric (cpuMhz);
    2908     pm::BaseMetric *ramUsage =
    2909         metricFactory->createHostRamUsage (objptr, ramUsageTotal, ramUsageUsed,
     2906    pm::BaseMetric *ramUsage = new pm::HostRamUsage (hal, objptr, ramUsageTotal, ramUsageUsed,
    29102907                                           ramUsageFree);
    29112908    aCollector->registerBaseMetric (ramUsage);
  • trunk/src/VBox/Main/MachineImpl.cpp

    r12066 r12400  
    76127612void Machine::registerMetrics (PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid)
    76137613{
    7614     pm::MetricFactory *metricFactory = aCollector->getMetricFactory();
     7614    pm::CollectorHAL *hal = aCollector->getHAL();
    76157615    /* Create sub metrics */
    76167616    pm::SubMetric *cpuLoadUser = new pm::SubMetric ("CPU/Load/User",
     
    76257625    ComObjPtr<Machine> tmp = aMachine;
    76267626    tmp.queryInterfaceTo (&objptr);
    7627     pm::BaseMetric *cpuLoad =
    7628         metricFactory->createMachineCpuLoad (objptr, pid,
     7627    pm::BaseMetric *cpuLoad = new pm::MachineCpuLoadRaw (hal, objptr, pid,
    76297628                                             cpuLoadUser, cpuLoadKernel);
    76307629    aCollector->registerBaseMetric (cpuLoad);
    7631     pm::BaseMetric *ramUsage =
    7632         metricFactory->createMachineRamUsage (objptr, pid, ramUsageUsed);
     7630    pm::BaseMetric *ramUsage = new pm::MachineRamUsage (hal, objptr, pid,
     7631                                                          ramUsageUsed);
    76337632    aCollector->registerBaseMetric (ramUsage);
    76347633
  • trunk/src/VBox/Main/Performance.cpp

    r12024 r12400  
    3636#include <iprt/cpuset.h>
    3737
     38#include <algorithm>
     39
    3840#include "Logging.h"
    3941#include "Performance.h"
    4042
    4143using namespace pm;
    42 
    43 // Default factory
    44 
    45 BaseMetric *MetricFactory::createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
    46 {
    47     Assert(mHAL);
    48     return new HostCpuLoadRaw(mHAL, object, user, kernel, idle);
    49 }
    50 BaseMetric *MetricFactory::createHostCpuMHz(ComPtr<IUnknown> object, SubMetric *mhz)
    51 {
    52     Assert(mHAL);
    53     return new HostCpuMhz(mHAL, object, mhz);
    54 }
    55 BaseMetric *MetricFactory::createHostRamUsage(ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available)
    56 {
    57     Assert(mHAL);
    58     return new HostRamUsage(mHAL, object, total, used, available);
    59 }
    60 BaseMetric *MetricFactory::createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)
    61 {
    62     Assert(mHAL);
    63     return new MachineCpuLoadRaw(mHAL, object, process, user, kernel);
    64 }
    65 BaseMetric *MetricFactory::createMachineRamUsage(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used)
    66 {
    67     Assert(mHAL);
    68     return new MachineRamUsage(mHAL, object, process, used);
    69 }
    7044
    7145// Stubs for non-pure virtual methods
     
    126100}
    127101
    128 void BaseMetric::collectorBeat(uint64_t nowAt)
     102bool BaseMetric::collectorBeat(uint64_t nowAt)
    129103{
    130104    if (isEnabled())
     
    135109            Log4(("{%p} " LOG_FN_FMT ": Collecting %s for obj(%p)...\n",
    136110                        this, __PRETTY_FUNCTION__, getName(), (void *)mObject));
    137             collect();
    138         }
    139     }
     111            return true;
     112        }
     113    }
     114    return false;
    140115}
    141116
     
    165140        mIdle->put(idle);
    166141    }
     142}
     143
     144void HostCpuLoadRaw::preCollect(CollectorHints& hints)
     145{
     146    hints.collectHostCpuLoad();
    167147}
    168148
     
    226206}
    227207
     208void HostRamUsage::preCollect(CollectorHints& hints)
     209{
     210    hints.collectHostRamUsage();
     211}
     212
    228213void HostRamUsage::collect()
    229214{
     
    259244}
    260245
     246void MachineCpuLoadRaw::preCollect(CollectorHints& hints)
     247{
     248    hints.collectProcessCpuLoad(mProcess);
     249}
     250
    261251void MachineCpuLoadRaw::collect()
    262252{
     
    289279    mLength = length;
    290280    mUsed->init(mLength);
     281}
     282
     283void MachineRamUsage::preCollect(CollectorHints& hints)
     284{
     285    hints.collectProcessRamUsage(mProcess);
    291286}
    292287
  • trunk/src/VBox/Main/PerformanceImpl.cpp

    r11583 r12400  
    108108    HRESULT rc = S_OK;
    109109
    110     /* @todo Obviously other platforms must be added as well. */
    111 #ifdef RT_OS_SOLARIS
    112     m.factory = new pm::MetricFactorySolaris();
    113 #endif
    114 #ifdef RT_OS_LINUX
    115     m.factory = new pm::MetricFactoryLinux();
    116 #endif
    117 #ifdef RT_OS_WINDOWS
    118     m.factory = new pm::MetricFactoryWin();
    119 #endif
    120 #ifdef RT_OS_OS2
    121     m.factory = new pm::MetricFactoryOS2();
    122 #endif
    123 #ifdef RT_OS_DARWIN
    124     m.factory = new pm::MetricFactoryDarwin();
    125 #endif
     110    m.hal = pm::createHAL();
    126111
    127112    /* Let the sampler know it gets a valid collector.  */
     
    170155    m.sampler = NULL;
    171156
    172     delete m.factory;
    173     m.factory = NULL;
     157    //delete m.factory;
     158    //m.factory = NULL;
     159
     160    delete m.hal;
     161    m.hal = NULL;
    174162
    175163    LogFlowThisFuncLeave();
     
    469457    AutoWriteLock alock (this);
    470458
     459    pm::CollectorHints hints;
    471460    uint64_t timestamp = RTTimeMilliTS();
     461    BaseMetricList toBeCollected;
     462    BaseMetricList::iterator it;
     463    /* Compose the list of metrics being collected at this moment */
     464    for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); it++)
     465        if ((*it)->collectorBeat(timestamp))
     466        {
     467            (*it)->preCollect(hints);
     468            toBeCollected.push_back(*it);
     469        }
     470
     471    /* Let know the platform specific code what is being collected */
     472    m.hal->preCollect(hints);
     473
     474    /* Finally, collect the data */
    472475    std::for_each (m.baseMetrics.begin(), m.baseMetrics.end(),
    473                    std::bind2nd (std::mem_fun (&pm::BaseMetric::collectorBeat),
    474                                  timestamp));
     476                   std::mem_fun (&pm::BaseMetric::collect));
    475477    Log4(("{%p} " LOG_FN_FMT ": LEAVE\n", this, __PRETTY_FUNCTION__));
    476478}
  • trunk/src/VBox/Main/darwin/PerformanceDarwin.cpp

    r12133 r12400  
    7474};
    7575
    76 MetricFactoryDarwin::MetricFactoryDarwin()
     76CollectorHAL *createHAL()
    7777{
    78     mHAL = new CollectorDarwin();
    79     Assert(mHAL);
     78    return new CollectorDarwin();
    8079}
    8180
  • trunk/src/VBox/Main/include/Performance.h

    r11583 r12400  
    2626#include <VBox/com/defs.h>
    2727#include <VBox/com/ptr.h>
     28#include <algorithm>
    2829#include <list>
    2930#include <string>
     31#include <vector>
    3032
    3133namespace pm
     
    6567
    6668    /* Collector Hardware Abstraction Layer *********************************/
     69    enum {
     70        COLLECT_NONE      = 0x0,
     71        COLLECT_CPU_LOAD  = 0x1,
     72        COLLECT_RAM_USAGE = 0x2
     73    };
     74    typedef int HintFlags;
     75    typedef std::pair<RTPROCESS, HintFlags> ProcessFlagsPair;
     76
     77    inline bool processEqual(ProcessFlagsPair pair, RTPROCESS process)
     78    {
     79        return pair.first == process;
     80    }
     81
     82    class CollectorHints
     83    {
     84        typedef std::list<ProcessFlagsPair> ProcessList;
     85
     86        HintFlags   mHostFlags;
     87        ProcessList mProcesses;
     88
     89        ProcessFlagsPair& findProcess(RTPROCESS process)
     90        {
     91            ProcessList::iterator it;
     92
     93            it = std::find_if(mProcesses.begin(),
     94                              mProcesses.end(),
     95                              std::bind2nd(std::ptr_fun(processEqual), process));
     96
     97            if (it != mProcesses.end())
     98                return *it;
     99
     100            /* Not found -- add new */
     101            mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE));
     102            return mProcesses.back();
     103        }
     104
     105    public:
     106        CollectorHints() : mHostFlags(COLLECT_NONE) {}
     107        void collectHostCpuLoad() { mHostFlags |= COLLECT_CPU_LOAD; }
     108        void collectHostRamUsage() { mHostFlags |= COLLECT_RAM_USAGE; }
     109        void collectProcessCpuLoad(RTPROCESS process)
     110        {
     111            findProcess(process).second |= COLLECT_CPU_LOAD;
     112        }
     113        void collectProcessRamUsage(RTPROCESS process)
     114        {
     115            findProcess(process).second |= COLLECT_RAM_USAGE;
     116        }
     117        bool isHostCpuLoadCollected() { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
     118        bool isHostRamUsageCollected() { return (mHostFlags & COLLECT_RAM_USAGE) != 0; }
     119        bool isProcessCpuLoadCollected(RTPROCESS process)
     120        {
     121            return (findProcess(process).second & COLLECT_CPU_LOAD) != 0;
     122        }
     123        bool isProcessRamUsageCollected(RTPROCESS process)
     124        {
     125            return (findProcess(process).second & COLLECT_RAM_USAGE) != 0;
     126        }
     127        void getProcesses(std::vector<RTPROCESS>& processes) const
     128        {
     129            processes.clear();
     130            processes.reserve(mProcesses.size());
     131            for (ProcessList::const_iterator it = mProcesses.begin(); it != mProcesses.end(); it++)
     132                processes.push_back(it->first);
     133        }
     134    };
     135
    67136    class CollectorHAL
    68137    {
    69138    public:
     139        virtual int preCollect(const CollectorHints& hints) { return VINF_SUCCESS; }
    70140        virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
    71141        virtual int getHostCpuMHz(ULONG *mhz);
     
    78148    };
    79149
     150    extern CollectorHAL *createHAL();
     151
    80152    /* Base Metrics *********************************************************/
    81153    class BaseMetric
     
    86158
    87159        virtual void init(ULONG period, ULONG length) = 0;
     160        virtual void preCollect(CollectorHints& hints) = 0;
    88161        virtual void collect() = 0;
    89162        virtual const char *getUnit() = 0;
     
    91164        virtual ULONG getMaxValue() = 0;
    92165
    93         void collectorBeat(uint64_t nowAt);
     166        bool collectorBeat(uint64_t nowAt);
    94167
    95168        void enable() { mEnabled = true; };
     
    137210        : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {};
    138211
     212        void preCollect(CollectorHints& hints);
    139213        void collect();
    140214    private:
     
    151225
    152226        void init(ULONG period, ULONG length);
     227        void preCollect(CollectorHints& hints) {}
    153228        void collect();
    154229        const char *getUnit() { return "MHz"; };
     
    166241
    167242        void init(ULONG period, ULONG length);
     243        void preCollect(CollectorHints& hints);
    168244        void collect();
    169245        const char *getUnit() { return "kB"; };
     
    199275        : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {};
    200276
     277        void preCollect(CollectorHints& hints);
    201278        void collect();
    202279    private:
     
    213290
    214291        void init(ULONG period, ULONG length);
     292        void preCollect(CollectorHints& hints);
    215293        void collect();
    216294        const char *getUnit() { return "kB"; };
     
    290368    };
    291369
    292     /* Metric Factories *****************************************************/
    293     class MetricFactory
    294     {
    295     public:
    296         MetricFactory() : mHAL(0) {};
    297         ~MetricFactory() { delete mHAL; };
    298 
    299         virtual BaseMetric   *createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle);
    300         virtual BaseMetric   *createHostCpuMHz(ComPtr<IUnknown> object, SubMetric *mhz);
    301         virtual BaseMetric   *createHostRamUsage(ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available);
    302         virtual BaseMetric   *createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel);
    303         virtual BaseMetric   *createMachineRamUsage(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used);
    304     protected:
    305         CollectorHAL *mHAL;
    306     };
    307 
    308     class MetricFactorySolaris : public MetricFactory
    309     {
    310     public:
    311         MetricFactorySolaris();
    312         // Nothing else to do here (yet)
    313     };
    314 
    315     class MetricFactoryLinux : public MetricFactory
    316     {
    317     public:
    318         MetricFactoryLinux();
    319         // Nothing else to do here (yet)
    320     };
    321 
    322     class MetricFactoryWin : public MetricFactory
    323     {
    324     public:
    325         MetricFactoryWin();
    326         // Nothing else to do here (yet)
    327     };
    328 
    329     class MetricFactoryOS2 : public MetricFactory
    330     {
    331     public:
    332         MetricFactoryOS2();
    333         // Nothing else to do here (yet)
    334     };
    335 
    336     class MetricFactoryDarwin : public MetricFactory
    337     {
    338     public:
    339         MetricFactoryDarwin();
    340         // Nothing else to do here (yet)
    341     };
     370    /* Filter Class *********************************************************/
    342371
    343372    class Filter
  • trunk/src/VBox/Main/include/PerformanceImpl.h

    r11583 r12400  
    3434
    3535#include <list>
    36 #include <set>
     36//#include <set>
    3737
    3838#include "Performance.h"
     
    107107};
    108108
    109 
    110 #if 0
    111 class ATL_NO_VTABLE PerformanceData :
    112     public VirtualBoxBaseNEXT,
    113     public VirtualBoxSupportTranslation <PerformanceData>,
    114     public IPerformanceData
    115 {
    116 private:
    117 
    118     struct Data
    119     {
    120         /* Constructor. */
    121         Data() { }
    122 
    123         bool operator== (const Data &that) const
    124         {
    125             return this == &that;
    126         }
    127     };
    128 
    129 public:
    130 
    131     VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (PerformanceData)
    132 
    133     DECLARE_NOT_AGGREGATABLE (PerformanceData)
    134 
    135     DECLARE_PROTECT_FINAL_CONSTRUCT()
    136 
    137     BEGIN_COM_MAP(PerformanceData)
    138         COM_INTERFACE_ENTRY (ISupportErrorInfo)
    139         COM_INTERFACE_ENTRY (IPerformanceData)
    140     END_COM_MAP()
    141 
    142     NS_DECL_ISUPPORTS
    143 
    144     DECLARE_EMPTY_CTOR_DTOR (PerformanceData)
    145 
    146     HRESULT FinalConstruct();
    147     void FinalRelease();
    148 
    149     // public initializer/uninitializer for internal purposes only
    150     HRESULT init (cosnt BSTR aMetricName, IUnknown *anObject,
    151                   ULONG *data, ULONG aLength);
    152     void uninit();
    153 
    154     // IPerformanceData properties
    155     STDMETHOD(COMGETTER(MetricName)) (BSTR *aMetricName);
    156     STDMETHOD(COMGETTER(Object)) (IUnknown **anObject);
    157     STDMETHOD(COMGETTER(Values)) (ComSafeArrayOut (LONG, values));
    158 
    159     // IPerformanceData methods
    160 
    161     // public methods only for internal purposes
    162 
    163 private:
    164 
    165     Bstr mMetricName;
    166     IUnknown *mObject;
    167     ULONG *mData;
    168     ULONG mLength;
    169 };
    170 #endif
    171109
    172110class ATL_NO_VTABLE PerformanceCollector :
     
    232170    // (ensure there is a caller and a read lock before calling them!)
    233171
    234     pm::MetricFactory *getMetricFactory() { return m.factory; };
     172    pm::CollectorHAL *getHAL() { return m.hal; };
    235173
    236174    // for VirtualBoxSupportErrorInfoImpl
     
    254192    struct Data
    255193    {
    256         Data() : factory(0) {};
     194        Data() : hal(0) {};
    257195
    258196        BaseMetricList     baseMetrics;
    259197        MetricList         metrics;
    260198        RTTIMERLR          sampler;
    261         pm::MetricFactory *factory;
     199        pm::CollectorHAL  *hal;
    262200    };
    263201
  • trunk/src/VBox/Main/linux/PerformanceLinux.cpp

    r11498 r12400  
    4343};
    4444
    45 // Linux Metric factory
    46 
    47 MetricFactoryLinux::MetricFactoryLinux()
     45CollectorHAL *createHAL()
    4846{
    49     mHAL = new CollectorLinux();
    50     Assert(mHAL);
     47    return new CollectorLinux();
    5148}
    5249
  • trunk/src/VBox/Main/os2/PerformanceOs2.cpp

    r11180 r12400  
    3737
    3838
    39 MetricFactoryOS2::MetricFactoryOS2()
     39CollectorHAL *createHAL()
    4040{
    41     mHAL = new CollectorOS2();
    42     Assert(mHAL);
     41    return new CollectorOS2();
    4342}
    4443
  • trunk/src/VBox/Main/solaris/PerformanceSolaris.cpp

    r11501 r12400  
    5555};
    5656
    57 // Solaris Metric factory
    58 
    59 MetricFactorySolaris::MetricFactorySolaris()
    60 {
    61     mHAL = new CollectorSolaris();
    62     Assert(mHAL);
     57CollectorHAL *createHAL()
     58{
     59    return new CollectorSolaris();
    6360}
    6461
  • trunk/src/VBox/Main/testcase/tstCollector.cpp

    r12136 r12400  
    2424#include <iprt/runtime.h>
    2525#include <iprt/stream.h>
     26#include <iprt/env.h>
    2627#include <iprt/err.h>
    2728#include <iprt/process.h>
     
    6667}
    6768
    68 #define CALLS_PER_SECOND(n,fn) \
     69#define RUN_TIME_MS        1000
     70
     71#define N_CALLS(n, fn) \
     72    for (int call = 0; call < n; ++call) \
     73        rc = collector->fn; \
     74    if (RT_FAILURE(rc)) \
     75        RTPrintf("tstCollector: "#fn" -> %Vrc\n", rc)
     76
     77#define CALLS_PER_SECOND(fn) \
    6978    nCalls = 0; \
    7079    start = RTTimeMilliTS(); \
     
    7281        rc = collector->fn; \
    7382        ++nCalls; \
    74     } while(RTTimeMilliTS() - start < 1000); \
     83    } while(RTTimeMilliTS() - start < RUN_TIME_MS); \
    7584    if (RT_FAILURE(rc)) \
    7685    { \
     
    7887    } \
    7988    else \
    80         RTPrintf("%50s -- %u calls per second\n", #fn, nCalls); \
    81     totalTime += n * 1000000 / nCalls
     89        RTPrintf("%70s -- %u calls per second\n", #fn, nCalls)
     90
     91void measurePerformance(pm::CollectorHAL *collector, const char *pszName, int cVMs)
     92{
     93
     94    static const char * const args[] = { pszName, "-child", NULL };
     95    pm::CollectorHints hints;
     96    std::vector<RTPROCESS> processes;
     97
     98    hints.collectHostCpuLoad();
     99    hints.collectHostRamUsage();
     100    /* Start fake VMs */
     101    for (int i = 0; i < cVMs; ++i)
     102    {
     103        RTPROCESS pid;
     104        int rc = RTProcCreate(pszName, args, RTENV_DEFAULT, 0, &pid);
     105        if (RT_FAILURE(rc))
     106        {
     107            hints.getProcesses(processes);
     108            std::for_each(processes.begin(), processes.end(), std::ptr_fun(RTProcTerminate));
     109            RTPrintf("tstCollector: RTProcCreate() -> %Vrc\n", rc);
     110            return;
     111        }
     112        hints.collectProcessCpuLoad(pid);
     113        hints.collectProcessRamUsage(pid);
     114    }
     115
     116    hints.getProcesses(processes);
     117    RTThreadSleep(30000); // Let children settle for half a minute
     118
     119    int rc;
     120    ULONG tmp;
     121    uint64_t tmp64;
     122    uint64_t start;
     123    unsigned int nCalls;
     124    uint32_t totalTime = 0;
     125    /* Pre-collect */
     126    CALLS_PER_SECOND(preCollect(hints));
     127    /* Host CPU load */
     128    CALLS_PER_SECOND(getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
     129    /* Process CPU load */
     130    CALLS_PER_SECOND(getRawProcessCpuLoad(processes[nCalls%cVMs], &tmp64, &tmp64, &tmp64));
     131    /* Host CPU speed */
     132    CALLS_PER_SECOND(getHostCpuMHz(&tmp));
     133    /* Host RAM usage */
     134    CALLS_PER_SECOND(getHostMemoryUsage(&tmp, &tmp, &tmp));
     135    /* Process RAM usage */
     136    CALLS_PER_SECOND(getProcessMemoryUsage(processes[nCalls%cVMs], &tmp));
     137
     138    start = RTTimeNanoTS();
     139
     140    for (int times = 0; times < 100; times++)
     141    {
     142        /* Pre-collect */
     143        N_CALLS(1, preCollect(hints));
     144        /* Host CPU load */
     145        N_CALLS(1, getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
     146        /* Host CPU speed */
     147        N_CALLS(1, getHostCpuMHz(&tmp));
     148        /* Host RAM usage */
     149        N_CALLS(1, getHostMemoryUsage(&tmp, &tmp, &tmp));
     150        /* Process CPU load */
     151        N_CALLS(cVMs, getRawProcessCpuLoad(processes[call], &tmp64, &tmp64, &tmp64));
     152        /* Process RAM usage */
     153        N_CALLS(cVMs, getProcessMemoryUsage(processes[call], &tmp));
     154    }
     155    printf("\n%u VMs -- %.2f%% of CPU time\n", cVMs, (RTTimeNanoTS() - start) / 10000000. / times);
     156
     157    /* Shut down fake VMs */
     158    std::for_each(processes.begin(), processes.end(), std::ptr_fun(RTProcTerminate));
     159}
    82160
    83161int main(int argc, char *argv[])
     
    91169    {
    92170        RTPrintf("tstCollector: RTR3Init() -> %d\n", rc);
     171        return 1;
     172    }
     173    if (argc > 1 && !strcmp(argv[1], "-child"))
     174    {
     175        /* We have spawned ourselves as a child process -- scratch the leg */
     176        RTThreadSleep(1000000);
    93177        return 1;
    94178    }
     
    108192#endif
    109193
    110     uint64_t start;
    111 
    112194    pm::CollectorHAL *collector = createCollector();
    113195    if (!collector)
     
    116198        return 1;
    117199    }
    118 #if 1
     200#if 0
     201    uint64_t start;
     202
    119203    uint64_t hostUserStart, hostKernelStart, hostIdleStart;
    120204    uint64_t hostUserStop, hostKernelStop, hostIdleStop, hostTotal;
     
    219303#endif
    220304    RTPrintf("\ntstCollector: TESTING - Performance\n\n");
    221     unsigned nCalls;
    222     ULONG tmp;
    223     uint64_t tmp64;
    224     uint32_t totalTime = 0;
    225     RTPROCESS pid = RTProcSelf();
    226     /* Host CPU load */
    227     CALLS_PER_SECOND(1, getRawHostCpuLoad(&tmp64, &tmp64, &tmp64));
    228     /* Process CPU load */
    229     CALLS_PER_SECOND(100, getRawProcessCpuLoad(pid, &tmp64, &tmp64, &tmp64));
    230     /* Host CPU speed */
    231     CALLS_PER_SECOND(1, getHostCpuMHz(&tmp));
    232     /* Host RAM usage */
    233     CALLS_PER_SECOND(1, getHostMemoryUsage(&tmp, &tmp, &tmp));
    234     /* Process RAM usage */
    235     CALLS_PER_SECOND(100, getProcessMemoryUsage(pid, &tmp));
    236    
    237     printf("%.2f%% of CPU time\n", totalTime / 10000.);
     305
     306    measurePerformance(collector, argv[0], 100);
    238307   
    239308    delete collector;
  • trunk/src/VBox/Main/win/PerformanceWin.cpp

    r11467 r12400  
    2929#include <iprt/mp.h>
    3030
     31#include <map>
     32
    3133#include "Logging.h"
    3234#include "Performance.h"
     
    4042    ~CollectorWin();
    4143
     44    virtual int preCollect(const CollectorHints& hints);
    4245    virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle);
    4346    virtual int getHostCpuMHz(ULONG *mhz);
     
    6972    long               mProcessCpuLoadTimestampHandle;
    7073    long               mProcessMemoryUsedHandle;
     74
     75    struct VMProcessStats
     76    {
     77        uint64_t cpuUser;
     78        uint64_t cpuKernel;
     79        uint64_t cpuTotal;
     80        uint64_t ramUsed;
     81    };
     82
     83    typedef std::map<RTPROCESS, VMProcessStats> VMProcessMap;
     84
     85    VMProcessMap       mProcessStats;
    7186};
    7287
    73 MetricFactoryWin::MetricFactoryWin()
    74 {
    75     mHAL = new CollectorWin();
    76     Assert(mHAL);
     88CollectorHAL *createHAL()
     89{
     90    return new CollectorWin();
    7791}
    7892
     
    265279}
    266280
    267 int CollectorWin::getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle)
    268 {
    269     return VERR_NOT_IMPLEMENTED;
    270 }
    271 
    272 int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
    273 {
     281int CollectorWin::preCollect(const CollectorHints& hints)
     282{
     283
     284    std::vector<RTPROCESS> processes;
     285    hints.getProcesses(processes);
     286
    274287    HRESULT hr;
    275288    IWbemObjectAccess       **apEnumAccess = NULL;
     
    283296        return VERR_INTERNAL_ERROR;
    284297    }
     298
     299    int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
     300    if (RT_FAILURE(rc))
     301        return rc;
     302
     303    rc = VERR_NOT_FOUND;
     304
     305    for (unsigned i = 0; i < dwNumReturned; i++)
     306    {
     307        DWORD dwIDProcess;
     308
     309        if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
     310            mProcessPIDHandle,
     311            &dwIDProcess)))
     312        {
     313            Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
     314            return VERR_INTERNAL_ERROR;
     315        }
     316        LogFlowThisFunc (("Matching process %x against the list of machines...\n", dwIDProcess));
     317        if (std::find(processes.begin(), processes.end(), dwIDProcess) != processes.end())
     318        {
     319            VMProcessStats vmStats;
     320
     321            LogFlowThisFunc (("Match found.\n"));
     322            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
     323                mProcessCpuLoadUserHandle,
     324                &vmStats.cpuUser)))
     325            {
     326                Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr));
     327                    return VERR_INTERNAL_ERROR;
     328            }
     329            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
     330                mProcessCpuLoadKernelHandle,
     331                &vmStats.cpuKernel)))
     332            {
     333                Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr));
     334                    return VERR_INTERNAL_ERROR;
     335            }
     336            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
     337                mProcessCpuLoadTimestampHandle,
     338                &vmStats.cpuTotal)))
     339            {
     340                Log (("Failed to read 'Timestamp_Sys100NS' property. HR = %x\n", hr));
     341                    return VERR_INTERNAL_ERROR;
     342            }
     343            if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
     344                mProcessMemoryUsedHandle,
     345                &vmStats.ramUsed)))
     346            {
     347                Log (("Failed to read 'WorkingSet' property. HR = %x\n", hr));
     348                    return VERR_INTERNAL_ERROR;
     349            }
     350
     351            mProcessStats[dwIDProcess] = vmStats;
     352            LogFlowThisFunc(("process=%x user=%lu kernel=%lu total=%lu\n", dwIDProcess, vmStats.cpuUser, vmStats.cpuKernel, vmStats.cpuTotal));
     353            rc = VINF_SUCCESS;
     354        }
     355        apEnumAccess[i]->Release();
     356        apEnumAccess[i] = NULL;
     357    }
     358    delete [] apEnumAccess;
     359
     360    LogFlowThisFuncLeave();
     361
     362    return rc;
     363}
     364
     365int CollectorWin::getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle)
     366{
     367    return VERR_NOT_IMPLEMENTED;
     368}
     369
     370int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
     371{
     372    HRESULT hr;
     373    IWbemObjectAccess       **apEnumAccess = NULL;
     374    DWORD                   dwNumReturned = 0;
     375
     376    LogFlowThisFuncEnter();
    285377
    286378    int rc = getObjects(mEnumProcessor, &apEnumAccess, &dwNumReturned);
     
    395487int CollectorWin::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
    396488{
    397     HRESULT hr;
    398     IWbemObjectAccess       **apEnumAccess = NULL;
    399     DWORD                   dwNumReturned = 0;
    400 
    401     LogFlowThisFuncEnter();
    402 
    403     if (FAILED (hr = mRefresher->Refresh(0L)))
    404     {
    405         Log (("Refresher failed. HR = %x\n", hr));
     489    VMProcessMap::const_iterator it = mProcessStats.find(process);
     490
     491    if (it == mProcessStats.end())
     492    {
     493        Log (("No stats pre-collected for process %x\n", process));
    406494        return VERR_INTERNAL_ERROR;
    407495    }
    408 
    409     int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
    410     if (RT_FAILURE(rc))
    411         return rc;
    412 
    413     rc = VERR_NOT_FOUND;
    414 
    415     for (unsigned i = 0; i < dwNumReturned; i++)
    416     {
    417         DWORD dwIDProcess;
    418 
    419         if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
    420             mProcessPIDHandle,
    421             &dwIDProcess)))
    422         {
    423             Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
    424             return VERR_INTERNAL_ERROR;
    425         }
    426         LogFlowThisFunc (("Matching machine process %x against %x...\n", process, dwIDProcess));
    427         if (dwIDProcess == process)
    428         {
    429             LogFlowThisFunc (("Match found.\n"));
    430             if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
    431                 mProcessCpuLoadUserHandle,
    432                 user)))
    433             {
    434             Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr));
    435                 return VERR_INTERNAL_ERROR;
    436             }
    437             if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
    438                 mProcessCpuLoadKernelHandle,
    439                 kernel)))
    440             {
    441             Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr));
    442                 return VERR_INTERNAL_ERROR;
    443             }
    444             if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
    445                 mProcessCpuLoadTimestampHandle,
    446                 total)))
    447             {
    448             Log (("Failed to read 'Timestamp_Sys100NS' property. HR = %x\n", hr));
    449                 return VERR_INTERNAL_ERROR;
    450             }
    451             rc = VINF_SUCCESS;
    452         }
    453         apEnumAccess[i]->Release();
    454         apEnumAccess[i] = NULL;
    455     }
    456     delete [] apEnumAccess;
    457 
    458     LogFlowThisFunc(("user=%lu kernel=%lu total=%lu\n", *user, *kernel, *total));
    459     LogFlowThisFuncLeave();
    460 
    461     return rc;
     496    *user   = it->second.cpuUser;
     497    *kernel = it->second.cpuKernel;
     498    *total  = it->second.cpuTotal;
     499    return VINF_SUCCESS;
    462500}
    463501
    464502int CollectorWin::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
    465503{
    466     HRESULT hr;
    467     IWbemObjectAccess       **apEnumAccess = NULL;
    468     DWORD                   dwNumReturned = 0;
    469 
    470     LogFlowThisFuncEnter();
    471 
    472     if (FAILED (hr = mRefresher->Refresh(0L)))
    473     {
    474         Log (("Refresher failed. HR = %x\n", hr));
     504    VMProcessMap::const_iterator it = mProcessStats.find(process);
     505
     506    if (it == mProcessStats.end())
     507    {
     508        Log (("No stats pre-collected for process %x\n", process));
    475509        return VERR_INTERNAL_ERROR;
    476510    }
    477 
    478     int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned);
    479     if (RT_FAILURE(rc))
    480         return rc;
    481 
    482     rc = VERR_NOT_FOUND;
    483 
    484     for (unsigned i = 0; i < dwNumReturned; i++)
    485     {
    486         DWORD dwIDProcess;
    487 
    488         if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
    489             mProcessPIDHandle,
    490             &dwIDProcess)))
    491         {
    492             Log (("Failed to read 'IDProcess' property. HR = %x\n", hr));
    493             return VERR_INTERNAL_ERROR;
    494         }
    495         if (dwIDProcess == process)
    496         {
    497             uint64_t u64used = 0;
    498 
    499             if (FAILED (hr = apEnumAccess[i]->ReadQWORD(
    500                 mProcessMemoryUsedHandle,
    501                 &u64used)))
    502             {
    503             Log (("Failed to read 'WorkingSet' property. HR = %x\n", hr));
    504                 return VERR_INTERNAL_ERROR;
    505             }
    506             *used = (ULONG)(u64used / 1024);
    507             rc = VINF_SUCCESS;
    508         }
    509         apEnumAccess[i]->Release();
    510         apEnumAccess[i] = NULL;
    511     }
    512     delete [] apEnumAccess;
    513 
    514     LogFlowThisFunc(("used=%lu\n", *used));
    515     LogFlowThisFuncLeave();
    516 
    517     return rc;
    518 }
    519 
    520 }
     511    *used = (ULONG)(it->second.ramUsed / 1024);
     512    return VINF_SUCCESS;
     513}
     514
     515}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette