VirtualBox

Changeset 43629 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Oct 12, 2012 9:26:07 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
81354
Message:

Main/Metrics: Linux fs/disk metrics, VBoxManage filtering + minor fixes (#6345)

Location:
trunk/src/VBox/Main/src-server
Files:
8 edited

Legend:

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

    r43525 r43629  
    28842884#ifdef VBOX_WITH_RESOURCE_USAGE_API
    28852885
     2886void Host::registerDiskMetrics(PerformanceCollector *aCollector)
     2887{
     2888    pm::CollectorHAL *hal = aCollector->getHAL();
     2889    /* Create sub metrics */
     2890    Utf8StrFmt fsNameBase("FS/{%s}/Usage", "/");
     2891    //Utf8StrFmt fsNameBase("Filesystem/[root]/Usage");
     2892    pm::SubMetric *fsRootUsageTotal  = new pm::SubMetric(fsNameBase + "/Total",
     2893        "Root file system size.");
     2894    pm::SubMetric *fsRootUsageUsed   = new pm::SubMetric(fsNameBase + "/Used",
     2895        "Root file system space currently occupied.");
     2896    pm::SubMetric *fsRootUsageFree   = new pm::SubMetric(fsNameBase + "/Free",
     2897        "Root file system space currently empty.");
     2898
     2899    pm::BaseMetric *fsRootUsage = new pm::HostFilesystemUsage(hal, this,
     2900                                                              fsNameBase, "/",
     2901                                                              fsRootUsageTotal,
     2902                                                              fsRootUsageUsed,
     2903                                                              fsRootUsageFree);
     2904    aCollector->registerBaseMetric (fsRootUsage);
     2905
     2906    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal, 0));
     2907    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
     2908                                              new pm::AggregateAvg()));
     2909    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
     2910                                              new pm::AggregateMin()));
     2911    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
     2912                                              new pm::AggregateMax()));
     2913
     2914    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed, 0));
     2915    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
     2916                                              new pm::AggregateAvg()));
     2917    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
     2918                                              new pm::AggregateMin()));
     2919    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
     2920                                              new pm::AggregateMax()));
     2921
     2922    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree, 0));
     2923    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
     2924                                              new pm::AggregateAvg()));
     2925    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
     2926                                              new pm::AggregateMin()));
     2927    aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
     2928                                              new pm::AggregateMax()));
     2929
     2930    /* For now we are concerned with the root file system only. */
     2931    pm::DiskList disks;
     2932    int rc = pm::getDiskListByFs("/", disks);
     2933    if (RT_FAILURE(rc) || disks.empty())
     2934        return;
     2935    pm::DiskList::iterator it;
     2936    for (it = disks.begin(); it != disks.end(); ++it)
     2937    {
     2938        Utf8StrFmt strName("Disk/%s/Load", it->c_str());
     2939        pm::SubMetric *fsLoadUtil   = new pm::SubMetric(strName + "/Util",
     2940            "Percentage of time disk was busy serving I/O requests.");
     2941        pm::BaseMetric *fsLoad = new pm::HostDiskLoadRaw(hal, this, strName,
     2942                                                         *it, fsLoadUtil);
     2943        aCollector->registerBaseMetric (fsLoad);
     2944
     2945        aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil, 0));
     2946        aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
     2947                                                  new pm::AggregateAvg()));
     2948        aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
     2949                                                  new pm::AggregateMin()));
     2950        aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
     2951                                                  new pm::AggregateMax()));
     2952    }
     2953}
     2954
    28862955void Host::registerMetrics(PerformanceCollector *aCollector)
    28872956{
     
    30173086    aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
    30183087                                              new pm::AggregateMax()));
     3088    registerDiskMetrics(aCollector);
    30193089}
    30203090
  • trunk/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp

    r43618 r43629  
    9595    Utf8StrFmt strName("Net/%ls/Load", mShortName.raw());
    9696    pm::SubMetric *networkLoadRx   = new pm::SubMetric(strName + "/Rx",
    97         "Percentage of network interface bandwidth used.");
     97        "Percentage of network interface receive bandwidth used.");
    9898    pm::SubMetric *networkLoadTx   = new pm::SubMetric(strName + "/Tx",
    99         "Percentage of network interface bandwidth used.");
     99        "Percentage of network interface transmit bandwidth used.");
    100100
    101101    /* Create and register base metrics */
  • trunk/src/VBox/Main/src-server/Performance.cpp

    r43618 r43629  
    6464}
    6565
     66int CollectorHAL::getRawHostDiskLoad(const char * /* name */, uint64_t * /* disk_ms */, uint64_t * /* total_ms */)
     67{
     68    return E_NOTIMPL;
     69}
     70
    6671int CollectorHAL::getRawProcessCpuLoad(RTPROCESS  /* process */, uint64_t * /* user */, uint64_t * /* kernel */, uint64_t * /* total */)
    6772{
     
    7075
    7176int CollectorHAL::getHostMemoryUsage(ULONG * /* total */, ULONG * /* used */, ULONG * /* available */)
     77{
     78    return E_NOTIMPL;
     79}
     80
     81int CollectorHAL::getHostFilesystemUsage(const char * /* name */, ULONG * /* total */, ULONG * /* used */, ULONG * /* available */)
    7282{
    7383    return E_NOTIMPL;
     
    705715}
    706716
     717void HostDiskLoadRaw::init(ULONG period, ULONG length)
     718{
     719    mPeriod = period;
     720    mLength = length;
     721    mUtil->init(mLength);
     722    int rc = mHAL->getRawHostDiskLoad(mDiskName.c_str(), &mDiskPrev, &mTotalPrev);
     723    AssertRC(rc);
     724}
     725
     726void HostDiskLoadRaw::preCollect(CollectorHints& hints, uint64_t /* iTick */)
     727{
     728    hints.collectHostCpuLoad();
     729}
     730
     731void HostDiskLoadRaw::collect()
     732{
     733    uint64_t disk, total;
     734
     735    int rc = mHAL->getRawHostDiskLoad(mDiskName.c_str(), &disk, &total);
     736    if (RT_SUCCESS(rc))
     737    {
     738        uint64_t diskDiff = disk - mDiskPrev;
     739        uint64_t totalDiff = total - mTotalPrev;
     740
     741        if (RT_UNLIKELY(totalDiff == 0))
     742        {
     743            Assert(totalDiff);
     744            LogFlowThisFunc(("Improbable! Less than millisecond passed! Disk=%s\n", mDiskName.c_str()));
     745            mUtil->put(0);
     746        }
     747        else if (diskDiff > totalDiff)
     748        {
     749            /*
     750             * It is possible that the disk spent more time than CPU because
     751             * CPU measurements are taken during the pre-collect phase. We try
     752             * to compensate for than by adding the extra to the next round of
     753             * measurements.
     754             */
     755            mUtil->put(PM_NETWORK_LOAD_MULTIPLIER);
     756            Assert((diskDiff - totalDiff) < mPeriod * 1000);
     757            if ((diskDiff - totalDiff) > mPeriod * 1000)
     758            {
     759                LogRel(("Disk utilization time exceeds CPU time by more"
     760                        " than the collection period (%llu ms)\n", diskDiff - totalDiff));
     761            }
     762            else
     763            {
     764                disk = mDiskPrev + totalDiff;
     765                LogFlowThisFunc(("Moved %u milliseconds to the next period.\n", (unsigned)(diskDiff - totalDiff)));
     766            }
     767        }
     768        else
     769        {
     770            mUtil->put((ULONG)(PM_NETWORK_LOAD_MULTIPLIER * diskDiff / totalDiff));
     771        }
     772
     773        mDiskPrev = disk;
     774        mTotalPrev = total;
     775    }
     776    else
     777        LogFlowThisFunc(("Failed to collect data: %Rrc (%d).\n", rc));
     778}
     779
    707780void HostCpuMhz::init(ULONG period, ULONG length)
    708781{
     
    738811    ULONG total, used, available;
    739812    int rc = mHAL->getHostMemoryUsage(&total, &used, &available);
     813    if (RT_SUCCESS(rc))
     814    {
     815        mTotal->put(total);
     816        mUsed->put(used);
     817        mAvailable->put(available);
     818
     819    }
     820}
     821
     822void HostFilesystemUsage::init(ULONG period, ULONG length)
     823{
     824    mPeriod = period;
     825    mLength = length;
     826    mTotal->init(mLength);
     827    mUsed->init(mLength);
     828    mAvailable->init(mLength);
     829}
     830
     831void HostFilesystemUsage::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
     832{
     833}
     834
     835void HostFilesystemUsage::collect()
     836{
     837    ULONG total, used, available;
     838    int rc = mHAL->getHostFilesystemUsage(mFsName.c_str(), &total, &used, &available);
    740839    if (RT_SUCCESS(rc))
    741840    {
  • trunk/src/VBox/Main/src-server/darwin/PerformanceDarwin.cpp

    r43556 r43629  
    162162}
    163163
     164int getDiskListByFs(const char *name, DiskList& list)
     165{
     166    return VERR_NOT_IMPLEMENTED;
    164167}
    165168
     169}
     170
  • trunk/src/VBox/Main/src-server/linux/PerformanceLinux.cpp

    r43512 r43629  
    1919
    2020#include <stdio.h>
     21#include <unistd.h>
     22#include <sys/statvfs.h>
     23#include <errno.h>
     24#include <mntent.h>
    2125#include <iprt/alloc.h>
     26#include <iprt/cdefs.h>
     27#include <iprt/ctype.h>
    2228#include <iprt/err.h>
    2329#include <iprt/param.h>
    2430#include <iprt/string.h>
     31#include <iprt/mp.h>
    2532
    2633#include <map>
     
    3542{
    3643public:
     44    CollectorLinux();
    3745    virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */);
    3846    virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
     47    virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
    3948    virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
    4049
    4150    virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
    4251    virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
     52    virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
    4353    virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
    4454private:
    45     virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
     55    virtual int _getRawHostCpuLoad();
    4656    int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed);
    4757
     
    5767    VMProcessMap mProcessStats;
    5868    uint64_t     mUser, mKernel, mIdle;
     69    uint64_t     mSingleUser, mSingleKernel, mSingleIdle;
     70    uint32_t     mHZ;
    5971};
    6072
     
    6577
    6678// Collector HAL for Linux
     79
     80CollectorLinux::CollectorLinux()
     81{
     82    long hz = sysconf(_SC_CLK_TCK);
     83    if (hz == -1)
     84    {
     85        LogRel(("CollectorLinux failed to obtain HZ from kernel, assuming 100.\n"));
     86        mHZ = 100;
     87    }
     88    else
     89        mHZ = hz;
     90    LogFlowThisFunc(("mHZ=%u\n", mHZ));
     91}
    6792
    6893int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */)
     
    84109    if (hints.isHostCpuLoadCollected() || mProcessStats.size())
    85110    {
    86         _getRawHostCpuLoad(&mUser, &mKernel, &mIdle);
    87     }
    88     return VINF_SUCCESS;
    89 }
    90 
    91 int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
    92 {
    93     int rc = VINF_SUCCESS;
    94     ULONG u32user, u32nice, u32kernel, u32idle;
     111        _getRawHostCpuLoad();
     112    }
     113    return VINF_SUCCESS;
     114}
     115
     116int CollectorLinux::_getRawHostCpuLoad()
     117{
     118    int rc = VINF_SUCCESS;
     119    long long unsigned uUser, uNice, uKernel, uIdle, uIowait, uIrq, uSoftirq;
    95120    FILE *f = fopen("/proc/stat", "r");
    96121
    97122    if (f)
    98123    {
    99         if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4)
    100         {
    101             *user   = (uint64_t)u32user + u32nice;
    102             *kernel = u32kernel;
    103             *idle   = u32idle;
     124        char szBuf[128];
     125        if (fgets(szBuf, sizeof(szBuf), f))
     126        {
     127            if (sscanf(szBuf, "cpu %llu %llu %llu %llu %llu %llu %llu",
     128                       &uUser, &uNice, &uKernel, &uIdle, &uIowait,
     129                       &uIrq, &uSoftirq) == 7)
     130            {
     131                mUser   = uUser + uNice;
     132                mKernel = uKernel + uIrq + uSoftirq;
     133                mIdle   = uIdle + uIowait;
     134            }
     135            /* Try to get single CPU stats. */
     136            if (fgets(szBuf, sizeof(szBuf), f))
     137            {
     138                if (sscanf(szBuf, "cpu0 %llu %llu %llu %llu %llu %llu %llu",
     139                           &uUser, &uNice, &uKernel, &uIdle, &uIowait,
     140                           &uIrq, &uSoftirq) == 7)
     141                {
     142                    mSingleUser   = uUser + uNice;
     143                    mSingleKernel = uKernel + uIrq + uSoftirq;
     144                    mSingleIdle   = uIdle + uIowait;
     145                }
     146                else
     147                {
     148                    /* Assume that this is not an SMP system. */
     149                    Assert(RTMpGetCount() == 1);
     150                    mSingleUser   = mUser;
     151                    mSingleKernel = mKernel;
     152                    mSingleIdle   = mIdle;
     153                }
     154            }
     155            else
     156                rc = VERR_FILE_IO_ERROR;
    104157        }
    105158        else
     
    161214
    162215    return rc;
     216}
     217
     218int CollectorLinux::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
     219{
     220    struct statvfs stats;
     221    const unsigned _MB = 1024 * 1024;
     222
     223    if (statvfs(path, &stats) == -1)
     224    {
     225        LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
     226        return VERR_ACCESS_DENIED;
     227    }
     228    uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
     229    *total = (ULONG)(cbBlock * stats.f_blocks / _MB);
     230    *used  = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
     231    *available = (ULONG)(cbBlock * stats.f_bavail / _MB);
     232
     233    return VINF_SUCCESS;
    163234}
    164235
     
    252323}
    253324
    254 }
    255 
     325int CollectorLinux::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
     326{
     327    int rc = VINF_SUCCESS;
     328    char szIfName[/*IFNAMSIZ*/ 16 + 36];
     329    long long unsigned int u64Busy, tmp;
     330
     331    RTStrPrintf(szIfName, sizeof(szIfName), "/sys/class/block/%s/stat", name);
     332    FILE *f = fopen(szIfName, "r");
     333    if (f)
     334    {
     335        if (fscanf(f, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
     336                   &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &u64Busy, &tmp) == 11)
     337        {
     338            *disk_ms   = u64Busy;
     339            *total_ms  = (uint64_t)(mSingleUser + mSingleKernel + mSingleIdle) * 1000 / mHZ;
     340        }
     341        else
     342            rc = VERR_FILE_IO_ERROR;
     343        fclose(f);
     344    }
     345    else
     346        rc = VERR_ACCESS_DENIED;
     347
     348    return rc;
     349}
     350
     351static char *getDiskName(char *pszDiskName, size_t cbDiskName, const char *pszDevName)
     352{
     353    unsigned cbName = 0;
     354    unsigned cbDevName = strlen(pszDevName);
     355    const char *pszEnd = pszDevName + cbDevName - 1;
     356    while (pszEnd > pszDevName && RT_C_IS_DIGIT(*pszEnd))
     357        pszEnd--;
     358    while (pszEnd > pszDevName && *pszEnd != '/')
     359    {
     360        cbName++;
     361        pszEnd--;
     362    }
     363    RTStrCopy(pszDiskName, RT_MIN(cbName + 1, cbDiskName), pszEnd + 1);
     364    return pszDiskName;
     365}
     366
     367
     368int getDiskListByFs(const char *pszPath, DiskList& listDisks)
     369{
     370    FILE *mtab = setmntent("/etc/mtab", "r");
     371    if (mtab)
     372    {
     373        struct mntent *mntent;
     374        while ((mntent = getmntent(mtab)))
     375        {
     376            if (strcmp(pszPath, mntent->mnt_dir) == 0)
     377            {
     378                char szDevName[32];
     379                listDisks.push_back(RTCString(getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname)));
     380                break;
     381            }
     382        }
     383        endmntent(mtab);
     384    }
     385    return VINF_SUCCESS;
     386}
     387
     388}
     389
  • trunk/src/VBox/Main/src-server/os2/PerformanceOs2.cpp

    r28800 r43629  
    6363}
    6464
     65int getDiskListByFs(const char *name, DiskList& list)
     66{
     67    return VERR_NOT_IMPLEMENTED;
    6568}
     69
     70}
  • trunk/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp

    r43618 r43629  
    329329}
    330330
    331 }
     331int getDiskListByFs(const char *name, DiskList& list)
     332{
     333    return VERR_NOT_IMPLEMENTED;
     334}
     335
     336}
  • trunk/src/VBox/Main/src-server/win/PerformanceWin.cpp

    r43550 r43629  
    350350}
    351351
    352 }
     352int getDiskListByFs(const char *name, DiskList& list)
     353{
     354    return VERR_NOT_IMPLEMENTED;
     355}
     356
     357}
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