diff options
| author | Michael Meskes <meskes@debian.org> | 2011-01-20 11:21:45 +0100 |
|---|---|---|
| committer | Michael Meskes <meskes@debian.org> | 2011-01-20 11:21:45 +0100 |
| commit | 14ee89c73b263c9a9e6e5bd300ef05c1ed41742a (patch) | |
| tree | ba2010adc07bd73710310b25adb8428ea866e067 /src/VBox/Main/src-server/linux/PerformanceLinux.cpp | |
| parent | 361589e3ae692db27161410309b92c6b89e1ec6c (diff) | |
| download | virtualbox-14ee89c73b263c9a9e6e5bd300ef05c1ed41742a.tar.gz | |
Imported Upstream version 4.0.2-dfsgupstream/4.0.2-dfsg
Diffstat (limited to 'src/VBox/Main/src-server/linux/PerformanceLinux.cpp')
| -rw-r--r-- | src/VBox/Main/src-server/linux/PerformanceLinux.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/linux/PerformanceLinux.cpp b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp new file mode 100644 index 000000000..af5c0c267 --- /dev/null +++ b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp @@ -0,0 +1,218 @@ +/* $Id: PerformanceLinux.cpp 33992 2010-11-11 13:57:03Z vboxsync $ */ + +/** @file + * + * VBox Linux-specific Performance Classes implementation. + */ + +/* + * Copyright (C) 2008 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <stdio.h> +#include <iprt/alloc.h> +#include <iprt/err.h> +#include <iprt/param.h> +#include <iprt/string.h> + +#include <map> +#include <vector> + +#include "Logging.h" +#include "Performance.h" + +namespace pm { + +class CollectorLinux : public CollectorHAL +{ +public: + virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */); + virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available); + virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used); + + virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); + virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); +private: + virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); + int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed); + + struct VMProcessStats + { + uint64_t cpuUser; + uint64_t cpuKernel; + ULONG pagesUsed; + }; + + typedef std::map<RTPROCESS, VMProcessStats> VMProcessMap; + + VMProcessMap mProcessStats; + uint64_t mUser, mKernel, mIdle; +}; + +CollectorHAL *createHAL() +{ + return new CollectorLinux(); +} + +// Collector HAL for Linux + +int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */) +{ + std::vector<RTPROCESS> processes; + hints.getProcesses(processes); + + std::vector<RTPROCESS>::iterator it; + for (it = processes.begin(); it != processes.end(); it++) + { + VMProcessStats vmStats; + int rc = getRawProcessStats(*it, &vmStats.cpuUser, &vmStats.cpuKernel, &vmStats.pagesUsed); + if (RT_FAILURE(rc)) + return rc; + mProcessStats[*it] = vmStats; + } + if (hints.isHostCpuLoadCollected() || mProcessStats.size()) + { + _getRawHostCpuLoad(&mUser, &mKernel, &mIdle); + } + return VINF_SUCCESS; +} + +int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle) +{ + int rc = VINF_SUCCESS; + ULONG u32user, u32nice, u32kernel, u32idle; + FILE *f = fopen("/proc/stat", "r"); + + if (f) + { + if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4) + { + *user = (uint64_t)u32user + u32nice; + *kernel = u32kernel; + *idle = u32idle; + } + else + rc = VERR_FILE_IO_ERROR; + fclose(f); + } + else + rc = VERR_ACCESS_DENIED; + + return rc; +} + +int CollectorLinux::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle) +{ + *user = mUser; + *kernel = mKernel; + *idle = mIdle; + return VINF_SUCCESS; +} + +int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total) +{ + VMProcessMap::const_iterator it = mProcessStats.find(process); + + if (it == mProcessStats.end()) + { + Log (("No stats pre-collected for process %x\n", process)); + return VERR_INTERNAL_ERROR; + } + *user = it->second.cpuUser; + *kernel = it->second.cpuKernel; + *total = mUser + mKernel + mIdle; + return VINF_SUCCESS; +} + +int CollectorLinux::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available) +{ + int rc = VINF_SUCCESS; + ULONG buffers, cached; + FILE *f = fopen("/proc/meminfo", "r"); + + if (f) + { + int processed = fscanf(f, "MemTotal: %u kB\n", total); + processed += fscanf(f, "MemFree: %u kB\n", available); + processed += fscanf(f, "Buffers: %u kB\n", &buffers); + processed += fscanf(f, "Cached: %u kB\n", &cached); + if (processed == 4) + { + *available += buffers + cached; + *used = *total - *available; + } + else + rc = VERR_FILE_IO_ERROR; + fclose(f); + } + else + rc = VERR_ACCESS_DENIED; + + return rc; +} + +int CollectorLinux::getProcessMemoryUsage(RTPROCESS process, ULONG *used) +{ + VMProcessMap::const_iterator it = mProcessStats.find(process); + + if (it == mProcessStats.end()) + { + Log (("No stats pre-collected for process %x\n", process)); + return VERR_INTERNAL_ERROR; + } + *used = it->second.pagesUsed * (PAGE_SIZE / 1024); + return VINF_SUCCESS; +} + +int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed) +{ + int rc = VINF_SUCCESS; + char *pszName; + pid_t pid2; + char c; + int iTmp; + long long unsigned int u64Tmp; + unsigned uTmp; + unsigned long ulTmp; + signed long ilTmp; + ULONG u32user, u32kernel; + char buf[80]; /* @todo: this should be tied to max allowed proc name. */ + + RTStrAPrintf(&pszName, "/proc/%d/stat", process); + //printf("Opening %s...\n", pszName); + FILE *f = fopen(pszName, "r"); + RTMemFree(pszName); + + if (f) + { + if (fscanf(f, "%d %79s %c %d %d %d %d %d %u %lu %lu %lu %lu %u %u " + "%ld %ld %ld %ld %ld %ld %llu %lu %u", + &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp, + &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel, + &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &u64Tmp, + &ulTmp, memPagesUsed) == 24) + { + Assert((pid_t)process == pid2); + *cpuUser = u32user; + *cpuKernel = u32kernel; + } + else + rc = VERR_FILE_IO_ERROR; + fclose(f); + } + else + rc = VERR_ACCESS_DENIED; + + return rc; +} + +} + |
