VirtualBox

Changeset 36128 in vbox


Ignore:
Timestamp:
Mar 2, 2011 5:44:04 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
70296
Message:

Main/Metrics: Hypervisor and guest metrics re-done (#5566)

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r36099 r36128  
    1448414484      <li>CPU/MHz</li>
    1448514485      <li>RAM/Usage</li>
     14486      <li>RAM/VMM</li>
    1448614487      </ul>
    1448714488
  • trunk/src/VBox/Main/include/MachineImpl.h

    r36082 r36128  
    860860    void registerMetrics(PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid);
    861861
    862     pm::CollectorGuestHAL  *mGuestHAL;
     862    pm::CollectorGuest     *mCollectorGuest;
    863863#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    864864
  • trunk/src/VBox/Main/include/Performance.h

    r36036 r36128  
    7373
    7474
    75     /* Collector Hardware Abstraction Layer *********************************/
    7675    enum {
    7776        COLLECT_NONE        = 0x0,
    7877        COLLECT_CPU_LOAD    = 0x1,
    79         COLLECT_RAM_USAGE   = 0x2
     78        COLLECT_RAM_USAGE   = 0x2,
     79        COLLECT_GUEST_STATS = 0x4
    8080    };
    8181    typedef int HintFlags;
     
    9292        void collectHostRamUsage()
    9393            { mHostFlags |= COLLECT_RAM_USAGE; }
     94        void collectHostRamVmm()
     95            { mHostFlags |= COLLECT_GUEST_STATS; }
    9496        void collectProcessCpuLoad(RTPROCESS process)
    9597            { findProcess(process).second |= COLLECT_CPU_LOAD; }
    9698        void collectProcessRamUsage(RTPROCESS process)
    9799            { findProcess(process).second |= COLLECT_RAM_USAGE; }
     100        void collectGuestStats(RTPROCESS process)
     101            { findProcess(process).second |= COLLECT_GUEST_STATS; }
    98102        bool isHostCpuLoadCollected() const
    99103            { return (mHostFlags & COLLECT_CPU_LOAD) != 0; }
    100104        bool isHostRamUsageCollected() const
    101105            { return (mHostFlags & COLLECT_RAM_USAGE) != 0; }
     106        bool isHostRamVmmCollected() const
     107            { return (mHostFlags & COLLECT_GUEST_STATS) != 0; }
    102108        bool isProcessCpuLoadCollected(RTPROCESS process)
    103109            { return (findProcess(process).second & COLLECT_CPU_LOAD) != 0; }
    104110        bool isProcessRamUsageCollected(RTPROCESS process)
    105111            { return (findProcess(process).second & COLLECT_RAM_USAGE) != 0; }
     112        bool isGuestStatsCollected(RTPROCESS process)
     113            { return (findProcess(process).second & COLLECT_GUEST_STATS) != 0; }
    106114        void getProcesses(std::vector<RTPROCESS>& processes) const
    107115        {
     
    132140    };
    133141
     142    /* Guest Collector Classes  *********************************/
     143    class CollectorGuest
     144    {
     145    public:
     146        CollectorGuest(Machine *machine, RTPROCESS process);
     147        ~CollectorGuest();
     148
     149        bool isEnabled()        { return mEnabled; };
     150        bool isValid()          { return mValid; };
     151        void invalidateStats()  { mValid = false; };
     152        int updateStats();
     153        int enable();
     154        int disable();
     155
     156        RTPROCESS getProcess()  { return mProcess; };
     157        ULONG getCpuUser()      { return mCpuUser; };
     158        ULONG getCpuKernel()    { return mCpuKernel; };
     159        ULONG getCpuIdle()      { return mCpuIdle; };
     160        ULONG getMemTotal()     { return mMemTotal; };
     161        ULONG getMemFree()      { return mMemFree; };
     162        ULONG getMemBalloon()   { return mMemBalloon; };
     163        ULONG getMemShared()    { return mMemShared; };
     164        ULONG getMemCache()     { return mMemCache; };
     165        ULONG getPageTotal()    { return mPageTotal; };
     166        ULONG getAllocVMM()     { return mAllocVMM; };
     167        ULONG getFreeVMM()      { return mFreeVMM; };
     168        ULONG getBalloonedVMM() { return mBalloonedVMM; };
     169        ULONG getSharedVMM()    { return mSharedVMM; };
     170
     171    private:
     172        bool                 mEnabled;
     173        bool                 mValid;
     174        Machine             *mMachine;
     175        RTPROCESS            mProcess;
     176        ComPtr<IConsole>     mConsole;
     177        ComPtr<IGuest>       mGuest;
     178        ULONG                mCpuUser;
     179        ULONG                mCpuKernel;
     180        ULONG                mCpuIdle;
     181        ULONG                mMemTotal;
     182        ULONG                mMemFree;
     183        ULONG                mMemBalloon;
     184        ULONG                mMemShared;
     185        ULONG                mMemCache;
     186        ULONG                mPageTotal;
     187        ULONG                mAllocVMM;
     188        ULONG                mFreeVMM;
     189        ULONG                mBalloonedVMM;
     190        ULONG                mSharedVMM;
     191    };
     192
     193    typedef std::list<CollectorGuest*> CollectorGuestList;
     194    class CollectorGuestManager
     195    {
     196    public:
     197        CollectorGuestManager() : mVMMStatsProvider(NULL) {};
     198        void registerGuest(CollectorGuest* pGuest);
     199        void unregisterGuest(CollectorGuest* pGuest);
     200        CollectorGuest *getVMMStatsProvider() { return mVMMStatsProvider; };
     201        void preCollect(CollectorHints& hints, uint64_t iTick);
     202    private:
     203        CollectorGuestList mGuests;
     204        CollectorGuest    *mVMMStatsProvider;
     205    };
     206
     207    /* Collector Hardware Abstraction Layer *********************************/
    134208    class CollectorHAL
    135209    {
    136210    public:
    137                  CollectorHAL() : mMemAllocVMM(0), mMemFreeVMM(0), mMemBalloonedVMM(0), mMemSharedVMM(0) {};
     211                 CollectorHAL() {};
    138212        virtual ~CollectorHAL() { };
    139213        virtual int preCollect(const CollectorHints& /* hints */, uint64_t /* iTick */) { return VINF_SUCCESS; }
     
    153227        /** Returns process' CPU usage counter in platform-specific units. */
    154228        virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
    155 
    156         /** Enable metrics collecting (if applicable) */
    157         virtual int enable();
    158         /** Disable metrics collecting (if applicable) */
    159         virtual int disable();
    160 
    161         virtual int setMemHypervisorStats(ULONG memAlloc, ULONG memFree, ULONG memBallooned, ULONG memShared)
    162         {
    163             mMemAllocVMM     = memAlloc;
    164             mMemFreeVMM      = memFree;
    165             mMemBalloonedVMM = memBallooned;
    166             mMemSharedVMM    = memShared;
    167             return S_OK;
    168         }
    169 
    170         virtual void getMemHypervisorStats(ULONG *pMemAlloc, ULONG *pMemFree, ULONG *pMemBallooned, ULONG *pMemShared)
    171         {
    172             *pMemAlloc     = mMemAllocVMM;
    173             *pMemFree      = mMemFreeVMM;
    174             *pMemBallooned = mMemBalloonedVMM;
    175             *pMemShared    = mMemSharedVMM;
    176         }
    177 
    178     private:
    179         ULONG       mMemAllocVMM;
    180         ULONG       mMemFreeVMM;
    181         ULONG       mMemBalloonedVMM;
    182         ULONG       mMemSharedVMM;
    183     };
    184 
    185     class CollectorGuestHAL : public CollectorHAL
    186     {
    187     public:
    188         CollectorGuestHAL(Machine *machine, CollectorHAL *hostHAL);
    189         ~CollectorGuestHAL();
    190 
    191         virtual int preCollect(const CollectorHints& hints, uint64_t iTick);
    192 
    193         /** Enable metrics collecting (if applicable) */
    194         virtual int enable();
    195         /** Disable metrics collecting (if applicable) */
    196         virtual int disable();
    197 
    198         /** Return guest cpu absolute load values (0-100). */
    199         void getGuestCpuLoad(ULONG *pulCpuUser, ULONG *pulCpuKernel, ULONG *pulCpuIdle)
    200         {
    201             *pulCpuUser   = mCpuUser;
    202             *pulCpuKernel = mCpuKernel;
    203             *pulCpuIdle   = mCpuIdle;
    204         }
    205 
    206         /** Return guest memory information in KB. */
    207         void getGuestMemLoad(ULONG *pulMemTotal, ULONG *pulMemFree, ULONG *pulMemBalloon, ULONG *pulMemShared, ULONG *pulMemCache, ULONG *pulPageTotal)
    208         {
    209             *pulMemTotal        = mMemTotal;
    210             *pulMemFree         = mMemFree;
    211             *pulMemBalloon      = mMemBalloon;
    212             *pulMemShared       = mMemShared;
    213             *pulMemCache        = mMemCache;
    214             *pulPageTotal       = mPageTotal;
    215         }
    216 
    217 
    218     protected:
    219         uint32_t             cEnabled;
    220         Machine             *mMachine;
    221         ComPtr<IConsole>     mConsole;
    222         ComPtr<IGuest>       mGuest;
    223         uint64_t             mLastTick;
    224 
    225         CollectorHAL        *mHostHAL;
    226 
    227         ULONG                mCpuUser;
    228         ULONG                mCpuKernel;
    229         ULONG                mCpuIdle;
    230         ULONG                mMemTotal;
    231         ULONG                mMemFree;
    232         ULONG                mMemBalloon;
    233         ULONG                mMemShared;
    234         ULONG                mMemCache;
    235         ULONG                mPageTotal;
    236 
    237     private:
    238         static uint32_t      cVMsEnabled;
    239229    };
    240230
     
    259249        bool collectorBeat(uint64_t nowAt);
    260250
    261         void enable()
    262         {
    263             mEnabled = true;
    264             mHAL->enable();
    265         };
    266         void disable()
    267         {
    268             mHAL->disable();
    269             mEnabled = false;
    270         };
     251        void enable()  { mEnabled = true; };
     252        void disable() { mEnabled = false; };
    271253
    272254        bool isEnabled() { return mEnabled; };
     
    287269    };
    288270
     271    class BaseGuestMetric : public BaseMetric
     272    {
     273    public:
     274        BaseGuestMetric(CollectorGuest *cguest, const char *name, ComPtr<IUnknown> object)
     275            : BaseMetric(NULL, name, object), mCGuest(cguest) {};
     276    protected:
     277        CollectorGuest *mCGuest;
     278    };
     279
    289280    class HostCpuLoad : public BaseMetric
    290281    {
     
    363354    {
    364355    public:
    365         HostRamVmm(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *allocVMM, SubMetric *freeVMM, SubMetric *balloonVMM, SubMetric *sharedVMM)
    366         : BaseMetric(hal, "RAM/VMM", object), mAllocVMM(allocVMM), mFreeVMM(freeVMM), mBalloonVMM(balloonVMM), mSharedVMM(sharedVMM) {};
     356        HostRamVmm(CollectorGuestManager *gm, ComPtr<IUnknown> object, SubMetric *allocVMM, SubMetric *freeVMM, SubMetric *balloonVMM, SubMetric *sharedVMM)
     357            : BaseMetric(NULL, "RAM/VMM", object), mCollectorGuestManager(gm),
     358            mAllocVMM(allocVMM), mFreeVMM(freeVMM), mBalloonVMM(balloonVMM), mSharedVMM(sharedVMM),
     359            mAllocCurrent(0), mFreeCurrent(0), mBalloonedCurrent(0), mSharedCurrent(0) {};
    367360        ~HostRamVmm() { delete mAllocVMM; delete mFreeVMM; delete mBalloonVMM; delete mSharedVMM; };
    368361
     
    374367        ULONG getMaxValue() { return INT32_MAX; };
    375368        ULONG getScale() { return 1; }
    376     private:
    377         SubMetric *mAllocVMM;
    378         SubMetric *mFreeVMM;
    379         SubMetric *mBalloonVMM;
    380         SubMetric *mSharedVMM;
     369
     370    private:
     371        CollectorGuestManager *mCollectorGuestManager;
     372        SubMetric             *mAllocVMM;
     373        SubMetric             *mFreeVMM;
     374        SubMetric             *mBalloonVMM;
     375        SubMetric             *mSharedVMM;
     376        ULONG                  mAllocCurrent;
     377        ULONG                  mFreeCurrent;
     378        ULONG                  mBalloonedCurrent;
     379        ULONG                  mSharedCurrent;
    381380    };
    382381
     
    434433
    435434
    436     class GuestCpuLoad : public BaseMetric
    437     {
    438     public:
    439         GuestCpuLoad(CollectorGuestHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
    440         : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle), mGuestHAL(hal) {};
     435    class GuestCpuLoad : public BaseGuestMetric
     436    {
     437    public:
     438        GuestCpuLoad(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)
     439            : BaseGuestMetric(cguest, "Guest/CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {};
    441440        ~GuestCpuLoad() { delete mUser; delete mKernel; delete mIdle; };
    442441
     
    452451        SubMetric *mKernel;
    453452        SubMetric *mIdle;
    454         CollectorGuestHAL *mGuestHAL;
    455     };
    456 
    457     class GuestRamUsage : public BaseMetric
    458     {
    459     public:
    460         GuestRamUsage(CollectorGuestHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *free, SubMetric *balloon, SubMetric *shared, SubMetric *cache, SubMetric *pagedtotal)
    461         : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mFree(free), mBallooned(balloon), mCache(cache), mPagedTotal(pagedtotal), mShared(shared), mGuestHAL(hal) {};
     453    };
     454
     455    class GuestRamUsage : public BaseGuestMetric
     456    {
     457    public:
     458        GuestRamUsage(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *total, SubMetric *free, SubMetric *balloon, SubMetric *shared, SubMetric *cache, SubMetric *pagedtotal)
     459            : BaseGuestMetric(cguest, "Guest/RAM/Usage", object), mTotal(total), mFree(free), mBallooned(balloon), mCache(cache), mPagedTotal(pagedtotal), mShared(shared) {};
    462460        ~GuestRamUsage() { delete mTotal; delete mFree; delete mBallooned; delete mShared; delete mCache; delete mPagedTotal; };
    463461
     
    471469    private:
    472470        SubMetric *mTotal, *mFree, *mBallooned, *mCache, *mPagedTotal, *mShared;
    473         CollectorGuestHAL *mGuestHAL;
    474471    };
    475472
  • trunk/src/VBox/Main/include/PerformanceImpl.h

    r35638 r36128  
    3636    class BaseMetric;
    3737    class CollectorHAL;
     38    class CollectorGuest;
     39    class CollectorGuestManager;
    3840}
    3941
     
    174176    void unregisterBaseMetricsFor (const ComPtr<IUnknown> &object);
    175177    void unregisterMetricsFor (const ComPtr<IUnknown> &object);
     178    void registerGuest(pm::CollectorGuest* pGuest);
     179    void unregisterGuest(pm::CollectorGuest* pGuest);
    176180
    177181    void suspendSampling();
     
    181185    // (ensure there is a caller and a read lock before calling them!)
    182186
    183     pm::CollectorHAL *getHAL() { return m.hal; };
     187    pm::CollectorHAL          *getHAL()          { return m.hal; };
     188    pm::CollectorGuestManager *getGuestManager() { return m.gm; };
    184189
    185190private:
     
    204209        Data() : hal(0) {};
    205210
    206         BaseMetricList     baseMetrics;
    207         MetricList         metrics;
    208         RTTIMERLR          sampler;
    209         pm::CollectorHAL  *hal;
     211        BaseMetricList             baseMetrics;
     212        MetricList                 metrics;
     213        RTTIMERLR                  sampler;
     214        pm::CollectorHAL          *hal;
     215        pm::CollectorGuestManager *gm;
    210216    };
    211217
  • trunk/src/VBox/Main/src-client/GuestImpl.cpp

    r36069 r36128  
    392392            *aMemSharedTotal  = (ULONG)(uSharedTotal / _1K);
    393393        }
     394        else
     395            return E_FAIL;
    394396
    395397        /* Query the missing per-VM memory statistics. */
     
    401403            *aMemShared = (ULONG)(uSharedMem / _1K);
    402404        }
     405        else
     406            return E_FAIL;
    403407    }
    404408    else
     
    409413        *aMemSharedTotal  = 0;
    410414        *aMemShared       = 0;
     415        return E_FAIL;
    411416    }
    412417
  • trunk/src/VBox/Main/src-server/HostImpl.cpp

    r36121 r36128  
    27942794                                                    ramUsageFree);
    27952795    aCollector->registerBaseMetric (ramUsage);
    2796     pm::BaseMetric *ramVmm = new pm::HostRamVmm(hal, objptr,
     2796    pm::BaseMetric *ramVmm = new pm::HostRamVmm(aCollector->getGuestManager(), objptr,
    27972797                                                ramVMMUsed,
    27982798                                                ramVMMFree,
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r36091 r36128  
    227227
    228228Machine::Machine()
    229     : mGuestHAL(NULL),
     229    : mCollectorGuest(NULL),
    230230      mPeer(NULL),
    231231      mParent(NULL)
     
    1006710067
    1006810068
    10069     /* Guest metrics */
    10070     mGuestHAL = new pm::CollectorGuestHAL(this, hal);
     10069    /* Guest metrics collector */
     10070    mCollectorGuest = new pm::CollectorGuest(aMachine, pid);
     10071    aCollector->registerGuest(mCollectorGuest);
     10072    LogAleksey(("{%p} " LOG_FN_FMT ": mCollectorGuest=%p\n",
     10073                this, __PRETTY_FUNCTION__, mCollectorGuest));
    1007110074
    1007210075    /* Create sub metrics */
     
    1008810091
    1008910092    /* Create and register base metrics */
    10090     pm::BaseMetric *guestCpuLoad = new pm::GuestCpuLoad(mGuestHAL, aMachine, guestLoadUser, guestLoadKernel, guestLoadIdle);
     10093    pm::BaseMetric *guestCpuLoad = new pm::GuestCpuLoad(mCollectorGuest, aMachine,
     10094                                                        guestLoadUser, guestLoadKernel, guestLoadIdle);
    1009110095    aCollector->registerBaseMetric(guestCpuLoad);
    1009210096
    10093     pm::BaseMetric *guestCpuMem = new pm::GuestRamUsage(mGuestHAL, aMachine, guestMemTotal, guestMemFree, guestMemBalloon, guestMemShared,
     10097    pm::BaseMetric *guestCpuMem = new pm::GuestRamUsage(mCollectorGuest, aMachine,
     10098                                                        guestMemTotal, guestMemFree,
     10099                                                        guestMemBalloon, guestMemShared,
    1009410100                                                        guestMemCache, guestPagedTotal);
    1009510101    aCollector->registerBaseMetric(guestCpuMem);
     
    1014910155        aCollector->unregisterMetricsFor(aMachine);
    1015010156        aCollector->unregisterBaseMetricsFor(aMachine);
    10151     }
    10152 
    10153     if (mGuestHAL)
    10154     {
    10155         delete mGuestHAL;
    10156         mGuestHAL = NULL;
    1015710157    }
    1015810158}
     
    1046510465    AutoMultiWriteLock3 multilock(mParent, mParent->host(), this COMMA_LOCKVAL_SRC_POS);
    1046610466
     10467    LogAleksey(("{%p} " LOG_FN_FMT ": mCollectorGuest=%p\n",
     10468                this, __PRETTY_FUNCTION__, mCollectorGuest));
     10469    if (mCollectorGuest)
     10470    {
     10471        mParent->performanceCollector()->unregisterGuest(mCollectorGuest);
     10472        delete mCollectorGuest;
     10473        mCollectorGuest = NULL;
     10474    }
    1046710475    // Trigger async cleanup tasks, avoid doing things here which are not
    1046810476    // vital to be done immediately and maybe need more locks. This calls
  • trunk/src/VBox/Main/src-server/Performance.cpp

    r36070 r36128  
    7676}
    7777
    78 int CollectorHAL::enable()
    79 {
    80     return E_NOTIMPL;
    81 }
    82 
    83 int  CollectorHAL::disable()
    84 {
    85     return E_NOTIMPL;
    86 }
    87 
    8878/* Generic implementations */
    8979
     
    121111#ifndef VBOX_COLLECTOR_TEST_CASE
    122112
    123 uint32_t CollectorGuestHAL::cVMsEnabled = 0;
    124 
    125 CollectorGuestHAL::CollectorGuestHAL(Machine *machine, CollectorHAL *hostHAL)
    126     : CollectorHAL(), cEnabled(0), mMachine(machine), mConsole(NULL),
    127       mGuest(NULL), mLastTick(0), mHostHAL(hostHAL), mCpuUser(0),
    128       mCpuKernel(0), mCpuIdle(0), mMemTotal(0), mMemFree(0),
    129       mMemBalloon(0), mMemShared(0), mMemCache(0), mPageTotal(0)
     113CollectorGuest::CollectorGuest(Machine *machine, RTPROCESS process) :
     114    mEnabled(false), mValid(false), mMachine(machine), mProcess(process),
     115    mCpuUser(0), mCpuKernel(0), mCpuIdle(0),
     116    mMemTotal(0), mMemFree(0), mMemBalloon(0), mMemShared(0), mMemCache(0), mPageTotal(0),
     117    mAllocVMM(0), mFreeVMM(0), mBalloonedVMM(0), mSharedVMM(0)
    130118{
    131119    Assert(mMachine);
     
    134122}
    135123
    136 CollectorGuestHAL::~CollectorGuestHAL()
     124CollectorGuest::~CollectorGuest()
    137125{
    138126    /* cannot use ComObjPtr<Machine> in Performance.h, do it manually */
    139127    mMachine->Release();
    140     Assert(!cEnabled);
    141 }
    142 
    143 int CollectorGuestHAL::enable()
    144 {
     128    // Assert(!cEnabled); why?
     129}
     130
     131int CollectorGuest::enable()
     132{
     133    mEnabled = true;
    145134    /* Must make sure that the machine object does not get uninitialized
    146135     * in the middle of enabling this collector. Causes timing-related
     
    154143    HRESULT ret = S_OK;
    155144
    156     if (ASMAtomicIncU32(&cEnabled) == 1)
    157     {
    158         ASMAtomicIncU32(&cVMsEnabled);
    159         ComPtr<IInternalSessionControl> directControl;
    160 
    161         ret = mMachine->getDirectControl(&directControl);
    162         if (ret != S_OK)
    163             return ret;
    164 
    165         /* get the associated console; this is a remote call (!) */
    166         ret = directControl->GetRemoteConsole(mConsole.asOutParam());
    167         if (ret != S_OK)
    168             return ret;
    169 
    170         ret = mConsole->COMGETTER(Guest)(mGuest.asOutParam());
    171         if (ret == S_OK)
    172             mGuest->COMSETTER(StatisticsUpdateInterval)(1 /* 1 sec */);
    173     }
     145    ComPtr<IInternalSessionControl> directControl;
     146
     147    ret = mMachine->getDirectControl(&directControl);
     148    if (ret != S_OK)
     149        return ret;
     150
     151    /* get the associated console; this is a remote call (!) */
     152    ret = directControl->GetRemoteConsole(mConsole.asOutParam());
     153    if (ret != S_OK)
     154        return ret;
     155
     156    ret = mConsole->COMGETTER(Guest)(mGuest.asOutParam());
     157    if (ret == S_OK)
     158    {
     159        ret = mGuest->COMSETTER(StatisticsUpdateInterval)(1 /* 1 sec */);
     160        LogAleksey(("{%p} " LOG_FN_FMT ": Set guest statistics update interval to 1 sec (%s)\n",
     161                    this, __PRETTY_FUNCTION__, SUCCEEDED(ret)?"success":"failed"));
     162    }
     163
    174164    return ret;
    175165}
    176166
    177 int CollectorGuestHAL::disable()
    178 {
    179     if (ASMAtomicDecU32(&cEnabled) == 0)
    180     {
    181         if (ASMAtomicDecU32(&cVMsEnabled) == 0)
    182         {
    183             if (mHostHAL)
    184                 mHostHAL->setMemHypervisorStats(0 /* ulMemAllocTotal */, 0 /* ulMemFreeTotal */, 0 /* ulMemBalloonTotal */, 0 /* ulMemSharedTotal */);
    185         }
    186         Assert(mGuest && mConsole);
    187         mGuest->COMSETTER(StatisticsUpdateInterval)(0 /* off */);
    188     }
     167int CollectorGuest::disable()
     168{
     169    mEnabled = false;
     170    Assert(mGuest && mConsole);
     171    HRESULT ret = mGuest->COMSETTER(StatisticsUpdateInterval)(0 /* off */);
     172    LogAleksey(("{%p} " LOG_FN_FMT ": Set guest statistics update interval to 0 sec (%s)\n",
     173                this, __PRETTY_FUNCTION__, SUCCEEDED(ret)?"success":"failed"));
     174    invalidateStats();
     175
    189176    return S_OK;
    190177}
    191178
    192 int CollectorGuestHAL::preCollect(const CollectorHints& /* hints */, uint64_t iTick)
    193 {
    194     if (    mGuest
    195         &&  iTick != mLastTick)
    196     {
    197         ULONG ulMemAllocTotal, ulMemFreeTotal, ulMemBalloonTotal, ulMemSharedTotal;
    198 
    199         mGuest->InternalGetStatistics(&mCpuUser, &mCpuKernel, &mCpuIdle,
    200                                       &mMemTotal, &mMemFree, &mMemBalloon, &mMemShared, &mMemCache,
    201                                       &mPageTotal, &ulMemAllocTotal, &ulMemFreeTotal, &ulMemBalloonTotal, &ulMemSharedTotal);
    202 
    203         if (mHostHAL)
    204             mHostHAL->setMemHypervisorStats(ulMemAllocTotal, ulMemFreeTotal, ulMemBalloonTotal, ulMemSharedTotal);
    205 
    206         mLastTick = iTick;
    207     }
     179int CollectorGuest::updateStats()
     180{
     181    if (mGuest)
     182    {
     183        HRESULT rc;
     184        rc = mGuest->InternalGetStatistics(&mCpuUser, &mCpuKernel, &mCpuIdle,
     185                                           &mMemTotal, &mMemFree, &mMemBalloon, &mMemShared, &mMemCache,
     186                                           &mPageTotal, &mAllocVMM, &mFreeVMM, &mBalloonedVMM, &mSharedVMM);
     187        if (SUCCEEDED(rc))
     188        {
     189            mValid = true;
     190        }
     191        LogAleksey(("{%p} " LOG_FN_FMT ": mValid=%s mCpuUser=%u mCpuKernel=%u mCpuIdle=%u\n"
     192                    "mMemTotal=%u mMemFree=%u mMemBalloon=%u mMemShared=%u mMemCache=%u\n"
     193                    "mPageTotal=%u mAllocVMM=%u mFreeVMM=%u mBalloonedVMM=%u mSharedVMM=%u\n",
     194                    this, __PRETTY_FUNCTION__, mValid?"y":"n",
     195                    mCpuUser, mCpuKernel, mCpuIdle,
     196                    mMemTotal, mMemFree, mMemBalloon, mMemShared, mMemCache,
     197                    mPageTotal, mAllocVMM, mFreeVMM, mBalloonedVMM, mSharedVMM));
     198    }
     199
    208200    return S_OK;
    209201}
     202
     203void CollectorGuestManager::preCollect(CollectorHints& hints, uint64_t /* iTick */)
     204{
     205    CollectorGuestList::iterator it;
     206
     207    LogAleksey(("{%p} " LOG_FN_FMT ": provider=%p ramvmm=%s\n",
     208                this, __PRETTY_FUNCTION__, mVMMStatsProvider, hints.isHostRamVmmCollected()?"y":"n"));
     209    for (it = mGuests.begin(); it != mGuests.end(); it++)
     210    {
     211        LogAleksey(("{%p} " LOG_FN_FMT ": it=%p pid=%d gueststats=%s...\n",
     212                    this, __PRETTY_FUNCTION__, *it, (*it)->getProcess(),
     213                    hints.isGuestStatsCollected((*it)->getProcess())?"y":"n"));
     214        if (  (hints.isHostRamVmmCollected() && *it == mVMMStatsProvider)
     215            || hints.isGuestStatsCollected((*it)->getProcess()))
     216        {
     217            /* Guest stats collection needs to be enabled */
     218            if ((*it)->isEnabled())
     219            {
     220                /* Already enabled, collect the data */
     221                (*it)->updateStats();
     222            }
     223            else
     224            {
     225                (*it)->invalidateStats();
     226                (*it)->enable();
     227            }
     228        }
     229        else
     230        {
     231            /* Guest stats collection needs to be disabled */
     232            if ((*it)->isEnabled())
     233                (*it)->disable();
     234        }
     235    }
     236}
     237
     238void CollectorGuestManager::registerGuest(CollectorGuest* pGuest)
     239{
     240    mGuests.push_back(pGuest);
     241    /*
     242     * If no VMM stats provider was elected previously than this is our
     243     * candidate.
     244     */
     245    if (!mVMMStatsProvider)
     246        mVMMStatsProvider = pGuest;
     247    LogAleksey(("{%p} " LOG_FN_FMT ": Registered guest=%p provider=%p\n",
     248                this, __PRETTY_FUNCTION__, pGuest, mVMMStatsProvider));
     249}
     250
     251void CollectorGuestManager::unregisterGuest(CollectorGuest* pGuest)
     252{
     253    LogAleksey(("{%p} " LOG_FN_FMT ": About to unregister guest=%p provider=%p\n",
     254                this, __PRETTY_FUNCTION__, pGuest, mVMMStatsProvider));
     255    mGuests.remove(pGuest);
     256    LogAleksey(("{%p} " LOG_FN_FMT ": Number of guests after remove is %d\n",
     257                this, __PRETTY_FUNCTION__, mGuests.size()));
     258    if (pGuest == mVMMStatsProvider)
     259    {
     260        /* This was our VMM stats provider, it is time to re-elect */
     261        if (mGuests.empty())
     262        {
     263            /* Nobody can provide VMM stats */
     264            mVMMStatsProvider = NULL;
     265        }
     266        else
     267        {
     268            /* First let's look for a guest already collecting stats */
     269            CollectorGuestList::iterator it;
     270
     271            for (it = mGuests.begin(); it != mGuests.end(); it++)
     272                if ((*it)->isEnabled())
     273                {
     274                    /* Found one, elect it */
     275                    mVMMStatsProvider = *it;
     276                    LogAleksey(("{%p} " LOG_FN_FMT ": LEAVE new provider=%p\n",
     277                                this, __PRETTY_FUNCTION__, mVMMStatsProvider));
     278                    return;
     279                }
     280
     281            /* Nobody collects stats, take the first one */
     282            mVMMStatsProvider = mGuests.front();
     283        }
     284    }
     285    LogAleksey(("{%p} " LOG_FN_FMT ": LEAVE new provider=%p\n",
     286                this, __PRETTY_FUNCTION__, mVMMStatsProvider));
     287}
     288
    210289
    211290#endif /* !VBOX_COLLECTOR_TEST_CASE */
     
    225304    return false;
    226305}
    227 
    228 /*bool BaseMetric::associatedWith(ComPtr<IUnknown> object)
    229 {
    230     LogFlowThisFunc(("mObject(%p) == object(%p) is %s.\n", mObject, object, mObject == object ? "true" : "false"));
    231     return mObject == object;
    232 }*/
    233306
    234307void HostCpuLoad::init(ULONG period, ULONG length)
     
    345418}
    346419
    347 void HostRamVmm::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
    348 {
    349     /*
    350      * This is an ugly ugly hack to force VMM metrics to 0s if no VM is
    351      * running. The reason it should work is that the VMM stats are
    352      * stored in CollectorHAL in preCollect methods of guest base metrics
    353      * which are always added after HostRamVmm. So each pass of collector
    354      * first clears the metrics then gets new values.
    355      */
    356     mHAL->setMemHypervisorStats(0 /* ulMemAllocTotal */, 0 /* ulMemFreeTotal */, 0 /* ulMemBalloonTotal */, 0 /* ulMemSharedTotal */);
     420void HostRamVmm::preCollect(CollectorHints& hints, uint64_t /* iTick */)
     421{
     422    hints.collectHostRamVmm();
    357423}
    358424
    359425void HostRamVmm::collect()
    360426{
    361     ULONG allocVMM, freeVMM, balloonVMM, sharedVMM;
    362 
    363     mHAL->getMemHypervisorStats(&allocVMM, &freeVMM, &balloonVMM, &sharedVMM);
    364     mAllocVMM->put(allocVMM);
    365     mFreeVMM->put(freeVMM);
    366     mBalloonVMM->put(balloonVMM);
    367     mSharedVMM->put(sharedVMM);
     427    CollectorGuest *provider = mCollectorGuestManager->getVMMStatsProvider();
     428    if (provider)
     429    {
     430        LogAleksey(("{%p} " LOG_FN_FMT ": provider=%p enabled=%s valid=%s...\n",
     431                    this, __PRETTY_FUNCTION__, provider, provider->isEnabled()?"y":"n",
     432                    provider->isValid()?"y":"n"));
     433        if (provider->isValid())
     434        {
     435            /* Provider is ready, get updated stats */
     436            mAllocCurrent     = provider->getAllocVMM();
     437            mFreeCurrent      = provider->getFreeVMM();
     438            mBalloonedCurrent = provider->getBalloonedVMM();
     439            mSharedCurrent    = provider->getSharedVMM();
     440        }
     441    }
     442    else
     443    {
     444        mAllocCurrent     = 0;
     445        mFreeCurrent      = 0;
     446        mBalloonedCurrent = 0;
     447        mSharedCurrent    = 0;
     448    }
     449    LogAleksey(("{%p} " LOG_FN_FMT ": mAllocCurrent=%u mFreeCurrent=%u mBalloonedCurrent=%u mSharedCurrent=%u\n",
     450                this, __PRETTY_FUNCTION__,
     451                mAllocCurrent, mFreeCurrent, mBalloonedCurrent, mSharedCurrent));
     452    mAllocVMM->put(mAllocCurrent);
     453    mFreeVMM->put(mFreeCurrent);
     454    mBalloonVMM->put(mBalloonedCurrent);
     455    mSharedVMM->put(mSharedCurrent);
    368456}
    369457
     
    450538}
    451539
    452 void GuestCpuLoad::preCollect(CollectorHints& hints, uint64_t iTick)
    453 {
    454     mHAL->preCollect(hints, iTick);
     540void GuestCpuLoad::preCollect(CollectorHints& hints, uint64_t /* iTick */)
     541{
     542    hints.collectGuestStats(mCGuest->getProcess());
    455543}
    456544
    457545void GuestCpuLoad::collect()
    458546{
    459     ULONG CpuUser = 0, CpuKernel = 0, CpuIdle = 0;
    460 
    461     mGuestHAL->getGuestCpuLoad(&CpuUser, &CpuKernel, &CpuIdle);
    462     mUser->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * CpuUser) / 100);
    463     mKernel->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * CpuKernel) / 100);
    464     mIdle->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * CpuIdle) / 100);
     547    if (mCGuest->isValid())
     548    {
     549        mUser->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuUser()) / 100);
     550        mKernel->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuKernel()) / 100);
     551        mIdle->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuIdle()) / 100);
     552    }
    465553}
    466554
     
    478566}
    479567
    480 void GuestRamUsage::preCollect(CollectorHints& hints,  uint64_t iTick)
    481 {
    482     mHAL->preCollect(hints, iTick);
     568void GuestRamUsage::preCollect(CollectorHints& hints,  uint64_t /* iTick */)
     569{
     570    hints.collectGuestStats(mCGuest->getProcess());
    483571}
    484572
    485573void GuestRamUsage::collect()
    486574{
    487     ULONG ulMemTotal = 0, ulMemFree = 0, ulMemBalloon = 0, ulMemShared = 0, ulMemCache = 0, ulPageTotal = 0;
    488 
    489     mGuestHAL->getGuestMemLoad(&ulMemTotal, &ulMemFree, &ulMemBalloon, &ulMemShared, &ulMemCache, &ulPageTotal);
    490     mTotal->put(ulMemTotal);
    491     mFree->put(ulMemFree);
    492     mBallooned->put(ulMemBalloon);
    493     mShared->put(ulMemShared);
    494     mCache->put(ulMemCache);
    495     mPagedTotal->put(ulPageTotal);
     575    if (mCGuest->isValid())
     576    {
     577        mTotal->put(mCGuest->getMemTotal());
     578        mFree->put(mCGuest->getMemFree());
     579        mBallooned->put(mCGuest->getMemBalloon());
     580        mShared->put(mCGuest->getMemShared());
     581        mCache->put(mCGuest->getMemCache());
     582        mPagedTotal->put(mCGuest->getPageTotal());
     583    }
    496584}
    497585
     
    792880    ElementList::const_iterator it;
    793881
    794     LogAleksey(("Filter::match(%p, %s)\n", static_cast<const IUnknown*> (object), name.c_str()));
     882    //LogAleksey(("Filter::match(%p, %s)\n", static_cast<const IUnknown*> (object), name.c_str()));
    795883    for (it = mElements.begin(); it != mElements.end(); it++)
    796884    {
    797         LogAleksey(("...matching against(%p, %s)\n", static_cast<const IUnknown*> ((*it).first), (*it).second.c_str()));
     885        //LogAleksey(("...matching against(%p, %s)\n", static_cast<const IUnknown*> ((*it).first), (*it).second.c_str()));
    798886        if ((*it).first.isNull() || (*it).first == object)
    799887        {
     
    806894        }
    807895    }
    808     LogAleksey(("...no matches!\n"));
     896    //LogAleksey(("...no matches!\n"));
    809897    return false;
    810898}
  • trunk/src/VBox/Main/src-server/PerformanceImpl.cpp

    r35638 r36128  
    159159
    160160    m.hal = pm::createHAL();
     161    m.gm = new pm::CollectorGuestManager;
    161162
    162163    /* Let the sampler know it gets a valid collector.  */
     
    208209    //m.factory = NULL;
    209210
     211    delete m.gm;
     212    m.gm = NULL;
    210213    delete m.hal;
    211214    m.hal = NULL;
     
    565568}
    566569
     570void PerformanceCollector::registerGuest(pm::CollectorGuest* pGuest)
     571{
     572    AutoCaller autoCaller(this);
     573    if (!SUCCEEDED(autoCaller.rc())) return;
     574
     575    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     576    m.gm->registerGuest(pGuest);
     577}
     578
     579void PerformanceCollector::unregisterGuest(pm::CollectorGuest* pGuest)
     580{
     581    AutoCaller autoCaller(this);
     582    if (!SUCCEEDED(autoCaller.rc())) return;
     583
     584    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     585    m.gm->unregisterGuest(pGuest);
     586}
     587
    567588void PerformanceCollector::suspendSampling()
    568589{
     
    600621}
    601622
     623/*
     624 * Metrics collection is a three stage process:
     625 * 1) Pre-collection (hinting)
     626 *    At this stage we compose the list of all metrics to be collected
     627 *    If any metrics cannot be collected separately or if it is more
     628 *    efficient to collect several metric at once, these metrics should
     629 *    use hints to mark that they will need to be collected.
     630 * 2) Pre-collection (bulk)
     631 *    Using hints set at stage 1 platform-specific HAL
     632 *    instance collects all marked host-related metrics.
     633 *    Hinted guest-related metrics then get collected by CollectorGuestManager.
     634 * 3) Collection
     635 *    Metrics that are collected individually get collected and stored. Values
     636 *    saved in HAL and CollectorGuestManager are extracted and stored to
     637 *    individual metrics.
     638 */
    602639void PerformanceCollector::samplerCallback(uint64_t iTick)
    603640{
     
    618655
    619656    if (toBeCollected.size() == 0)
     657    {
     658        Log4(("{%p} " LOG_FN_FMT ": LEAVE (nothing to collect)\n", this, __PRETTY_FUNCTION__));
    620659        return;
     660    }
    621661
    622662    /* Let know the platform specific code what is being collected */
    623663    m.hal->preCollect(hints, iTick);
     664    /* Collect the data in bulk from all hinted guests */
     665    m.gm->preCollect(hints, iTick);
    624666
    625667    /* Finally, collect the data */
  • trunk/src/VBox/Main/testcase/tstAPI.cpp

    r33595 r36128  
    12221222
    12231223        // Fill base metrics array
    1224         Bstr baseMetricNames[] = { L"CPU/Load,RAM/Usage" };
     1224        //Bstr baseMetricNames[] = { L"CPU/Load,RAM/Usage" };
     1225        Bstr baseMetricNames[] = { L"RAM/VMM" };
    12251226        com::SafeArray<BSTR> baseMetrics(1);
    12261227        baseMetricNames[0].cloneTo(&baseMetrics[0]);
     
    12351236        Bstr sessionType = argc > 2 ? argv[2] : "headless";
    12361237        RTPrintf("Getting a machine object named '%ls'...\n", name.raw());
    1237         CHECK_RC_BREAK(virtualBox->FindMachine(name, machine.asOutParam()));
     1238        CHECK_ERROR_BREAK(virtualBox, FindMachine(name.raw(), machine.asOutParam()));
    12381239
    12391240        // Open session
    1240         Guid guid;
    1241         CHECK_RC_BREAK(machine->COMGETTER(Id)(guid.asOutParam()));
    1242         RTPrintf("Opening a remote session for this machine...\n");
    12431241        ComPtr<IProgress> progress;
    1244         CHECK_RC_BREAK(virtualBox->OpenRemoteSession(session, guid, sessionType,
    1245                                                        NULL, progress.asOutParam()));
    1246         RTPrintf("Waiting for the session to open...\n");
    1247         CHECK_RC_BREAK(progress->WaitForCompletion(-1));
    1248         ComPtr<IMachine> sessionMachine;
    1249         RTPrintf("Getting machine session object...\n");
    1250         CHECK_RC_BREAK(session->COMGETTER(Machine)(sessionMachine.asOutParam()));
     1242        RTPrintf("Launching VM process...\n");
     1243        CHECK_ERROR_BREAK(machine, LaunchVMProcess(session, sessionType.raw(),
     1244                                                   NULL, progress.asOutParam()));
     1245        RTPrintf("Waiting for the VM to power on...\n");
     1246        CHECK_ERROR_BREAK(progress, WaitForCompletion(-1));
     1247
     1248        // ComPtr<IMachine> sessionMachine;
     1249        // RTPrintf("Getting machine session object...\n");
     1250        // CHECK_ERROR_BREAK(session, COMGETTER(Machine)(sessionMachine.asOutParam()));
    12511251
    12521252        // Setup base metrics
    12531253        // Note that one needs to set up metrics after a session is open for a machine.
    12541254        com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
    1255         com::SafeIfaceArray<IUnknown> objects(2);
     1255        com::SafeIfaceArray<IUnknown> objects(1);
    12561256        host.queryInterfaceTo(&objects[0]);
    1257         machine.queryInterfaceTo(&objects[1]);
     1257        //machine.queryInterfaceTo(&objects[1]);
    12581258        CHECK_ERROR_BREAK(collector, SetupMetrics(ComSafeArrayAsInParam(baseMetrics),
    12591259                                                   ComSafeArrayAsInParam(objects), 1u, 10u,
     
    12661266        ComPtr<IConsole> console;
    12671267        RTPrintf("Getting console object...\n");
    1268         CHECK_RC_BREAK(session->COMGETTER(Console)(console.asOutParam()));
     1268        CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
    12691269
    12701270        RTThreadSleep(5000); // Sleep for 5 seconds
     
    12761276        //RTPrintf("Press enter to pause the VM execution in the remote session...");
    12771277        //getchar();
    1278         CHECK_RC(console->Pause());
     1278        CHECK_ERROR_BREAK(console, Pause());
    12791279
    12801280        RTThreadSleep(5000); // Sleep for 5 seconds
     
    13211321        RTPrintf("Press enter to power off VM...");
    13221322        getchar();
    1323         CHECK_RC(console->PowerDown());
     1323        CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
     1324        RTPrintf("Waiting for the VM to power down...\n");
     1325        CHECK_ERROR_BREAK(progress, WaitForCompletion(-1));
    13241326        RTPrintf("Press enter to close this session...");
    13251327        getchar();
    1326         session->Close();
     1328        session->UnlockMachine();
    13271329    } while (false);
    13281330#endif /* VBOX_WITH_RESOURCE_USAGE_API */
Note: See TracChangeset for help on using the changeset viewer.

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