Changeset 43629 in vbox for trunk/src/VBox/Main/src-server/linux
- Timestamp:
- Oct 12, 2012 9:26:07 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/linux/PerformanceLinux.cpp
r43512 r43629 19 19 20 20 #include <stdio.h> 21 #include <unistd.h> 22 #include <sys/statvfs.h> 23 #include <errno.h> 24 #include <mntent.h> 21 25 #include <iprt/alloc.h> 26 #include <iprt/cdefs.h> 27 #include <iprt/ctype.h> 22 28 #include <iprt/err.h> 23 29 #include <iprt/param.h> 24 30 #include <iprt/string.h> 31 #include <iprt/mp.h> 25 32 26 33 #include <map> … … 35 42 { 36 43 public: 44 CollectorLinux(); 37 45 virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */); 38 46 virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available); 47 virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available); 39 48 virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used); 40 49 41 50 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); 42 51 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); 43 53 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); 44 54 private: 45 virtual int _getRawHostCpuLoad( uint64_t *user, uint64_t *kernel, uint64_t *idle);55 virtual int _getRawHostCpuLoad(); 46 56 int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed); 47 57 … … 57 67 VMProcessMap mProcessStats; 58 68 uint64_t mUser, mKernel, mIdle; 69 uint64_t mSingleUser, mSingleKernel, mSingleIdle; 70 uint32_t mHZ; 59 71 }; 60 72 … … 65 77 66 78 // Collector HAL for Linux 79 80 CollectorLinux::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 } 67 92 68 93 int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */) … … 84 109 if (hints.isHostCpuLoadCollected() || mProcessStats.size()) 85 110 { 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 116 int CollectorLinux::_getRawHostCpuLoad() 117 { 118 int rc = VINF_SUCCESS; 119 long long unsigned uUser, uNice, uKernel, uIdle, uIowait, uIrq, uSoftirq; 95 120 FILE *f = fopen("/proc/stat", "r"); 96 121 97 122 if (f) 98 123 { 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; 104 157 } 105 158 else … … 161 214 162 215 return rc; 216 } 217 218 int 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; 163 234 } 164 235 … … 252 323 } 253 324 254 } 255 325 int 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 351 static 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 368 int 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
Note:
See TracChangeset
for help on using the changeset viewer.