Changeset 10868 in vbox
- Timestamp:
- Jul 24, 2008 6:34:35 PM (16 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r10797 r10868 7361 7361 7362 7362 #ifdef VBOX_WITH_RESOURCE_USAGE_API 7363 void Machine::registerMetrics (PerformanceCollector *aCollector )7363 void Machine::registerMetrics (PerformanceCollector *aCollector, RTPROCESS pid) 7364 7364 { 7365 7365 pm::MetricFactory *metricFactory = aCollector->getMetricFactory(); … … 7367 7367 pm::SubMetric *cpuLoadUser = new pm::SubMetric ("CPU/Load/User"); 7368 7368 pm::SubMetric *cpuLoadKernel = new pm::SubMetric ("CPU/Load/Kernel"); 7369 pm::SubMetric *ramUsageUsed = new pm::SubMetric ("RAM/Usage/Used"); 7369 7370 /* Create and register base metrics */ 7370 7371 IUnknown *objptr; … … 7373 7374 tmp.queryInterfaceTo (&objptr); 7374 7375 pm::BaseMetric *cpuLoad = 7375 metricFactory->createMachineCpuLoad (objptr, mData->mSession.mPid,7376 metricFactory->createMachineCpuLoad (objptr, pid, 7376 7377 cpuLoadUser, cpuLoadKernel); 7377 7378 aCollector->registerBaseMetric (cpuLoad); 7379 pm::BaseMetric *ramUsage = 7380 metricFactory->createMachineRamUsage (objptr, pid, ramUsageUsed); 7381 aCollector->registerBaseMetric (ramUsage); 7378 7382 7379 7383 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser, 0)); … … 7391 7395 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel, 7392 7396 new pm::AggregateMax())); 7397 7398 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 0)); 7399 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 7400 new pm::AggregateAvg())); 7401 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 7402 new pm::AggregateMin())); 7403 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 7404 new pm::AggregateMax())); 7393 7405 }; 7394 7406 … … 7614 7626 } 7615 7627 7628 #ifdef VBOX_WITH_RESOURCE_USAGE_API 7629 registerMetrics (mParent->performanceCollector(), mData->mSession.mPid); 7630 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 7631 7616 7632 /* Confirm a successful initialization when it's the case */ 7617 7633 autoInitSpan.setSucceeded(); … … 7687 7703 AutoMultiWriteLock2 alock (mParent, this); 7688 7704 7705 #ifdef VBOX_WITH_RESOURCE_USAGE_API 7706 unregisterMetrics (mParent->performanceCollector()); 7707 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 7708 7689 7709 MachineState_T lastState = mData->mMachineState; 7690 7710 -
trunk/src/VBox/Main/Makefile.kmk
r10797 r10868 273 273 VBoxSVC_SOURCES.solaris += solaris/PerformanceSolaris.cpp 274 274 VBoxSVC_SOURCES.win += win/PerformanceWin.cpp 275 VBoxSVC_LDFLAGS.win += PDH.LIB275 VBoxSVC_LDFLAGS.win += wbemuuid.lib 276 276 endif 277 277 -
trunk/src/VBox/Main/Performance.cpp
r10753 r10868 22 22 */ 23 23 24 /* 25 * @todo list: 26 * 27 * 1) Solaris backend 28 * 2) Linux backend 29 * 3) Detection of erroneous metric names 30 * 4) Min/max ranges for metrics 31 * 5) Darwin backend 32 * 6) [OS/2 backend] 33 */ 34 24 35 #include <VBox/com/array.h> 25 36 #include <VBox/com/ptr.h> … … 29 40 #include <iprt/mem.h> 30 41 42 #include "Logging.h" 31 43 #include "Performance.h" 32 44 … … 38 50 { 39 51 Assert(mHAL); 40 return new HostCpuLoad (mHAL, object, user, kernel, idle);52 return new HostCpuLoadRaw(mHAL, object, user, kernel, idle); 41 53 } 42 54 BaseMetric *MetricFactory::createHostCpuMHz(ComPtr<IUnknown> object, SubMetric *mhz) … … 53 65 { 54 66 Assert(mHAL); 55 return new MachineCpuLoad (mHAL, object, process, user, kernel);67 return new MachineCpuLoadRaw(mHAL, object, process, user, kernel); 56 68 } 57 69 BaseMetric *MetricFactory::createMachineRamUsage(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used) … … 73 85 } 74 86 75 int CollectorHAL::getRawHostCpuLoad(u nsigned long *user, unsigned long *kernel, unsigned long*idle)87 int CollectorHAL::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle) 76 88 { 77 89 return E_NOTIMPL; 78 90 } 79 91 80 int CollectorHAL::getRawProcessCpuLoad(RTPROCESS process, u nsigned long *user, unsigned long *kernel)92 int CollectorHAL::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total) 81 93 { 82 94 return E_NOTIMPL; … … 90 102 { 91 103 mLastSampleTaken = nowAt; 104 LogFlowThisFunc (("Collecting data for obj(%p)...\n", mObject)); 92 105 collect(); 93 106 } 94 107 } 95 108 } 109 110 /*bool BaseMetric::associatedWith(ComPtr<IUnknown> object) 111 { 112 LogFlowThisFunc (("mObject(%p) == object(%p) is %s.\n", mObject, object, mObject == object ? "true" : "false")); 113 return mObject == object; 114 }*/ 96 115 97 116 void HostCpuLoad::init(unsigned long period, unsigned long length) … … 118 137 void HostCpuLoadRaw::collect() 119 138 { 120 u nsigned longuser, kernel, idle;121 u nsigned longuserDiff, kernelDiff, idleDiff, totalDiff;139 uint64_t user, kernel, idle; 140 uint64_t userDiff, kernelDiff, idleDiff, totalDiff; 122 141 123 142 int rc = mHAL->getRawHostCpuLoad(&user, &kernel, &idle); … … 128 147 idleDiff = idle - mIdlePrev; 129 148 totalDiff = userDiff + kernelDiff + idleDiff; 130 131 mUser->put(PM_CPU_LOAD_MULTIPLIER * userDiff / totalDiff); 132 mKernel->put(PM_CPU_LOAD_MULTIPLIER * kernelDiff / totalDiff); 133 mIdle->put(PM_CPU_LOAD_MULTIPLIER * idleDiff / totalDiff); 149 150 if (totalDiff == 0) 151 { 152 /* This is only possible if none of counters has changed! */ 153 LogFlowThisFunc (("Impossible! User, kernel and idle raw " 154 "counters has not changed since last sample.\n" )); 155 mUser->put(0); 156 mKernel->put(0); 157 mIdle->put(0); 158 } 159 else 160 { 161 mUser->put((unsigned long)(PM_CPU_LOAD_MULTIPLIER * userDiff / totalDiff)); 162 mKernel->put((unsigned long)(PM_CPU_LOAD_MULTIPLIER * kernelDiff / totalDiff)); 163 mIdle->put((unsigned long)(PM_CPU_LOAD_MULTIPLIER * idleDiff / totalDiff)); 164 } 134 165 135 166 mUserPrev = user; … … 198 229 void MachineCpuLoadRaw::collect() 199 230 { 200 unsigned long hostUser, hostKernel, hostIdle, hostTotal; 201 unsigned long processUser, processKernel; 202 203 int rc = mHAL->getRawHostCpuLoad(&hostUser, &hostKernel, &hostIdle); 204 if (RT_SUCCESS(rc)) 205 { 206 hostTotal = hostUser + hostKernel + hostIdle; 231 uint64_t processUser, processKernel, hostTotal; 232 233 int rc = mHAL->getRawProcessCpuLoad(mProcess, &processUser, &processKernel, &hostTotal); 234 if (RT_SUCCESS(rc)) 235 { 236 if (hostTotal == mHostTotalPrev) 237 { 238 /* Nearly impossible, but... */ 239 mUser->put(0); 240 mKernel->put(0); 241 } 242 else 243 { 244 mUser->put((unsigned long)(PM_CPU_LOAD_MULTIPLIER * (processUser - mProcessUserPrev) / (hostTotal - mHostTotalPrev))); 245 mKernel->put((unsigned long)(PM_CPU_LOAD_MULTIPLIER * (processKernel - mProcessKernelPrev ) / (hostTotal - mHostTotalPrev))); 246 } 207 247 208 rc = mHAL->getRawProcessCpuLoad(mProcess, &processUser, &processKernel); 209 AssertRC(rc); 210 if (RT_SUCCESS(rc)) 211 { 212 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processUser - mProcessUserPrev) / (hostTotal - mHostTotalPrev)); 213 mUser->put(PM_CPU_LOAD_MULTIPLIER * (processKernel - mProcessKernelPrev ) / (hostTotal - mHostTotalPrev)); 214 215 mHostTotalPrev = hostTotal; 216 mProcessUserPrev = processUser; 217 mProcessKernelPrev = processKernel; 218 } 248 mHostTotalPrev = hostTotal; 249 mProcessUserPrev = processUser; 250 mProcessKernelPrev = processKernel; 219 251 } 220 252 } … … 270 302 // Copy the wrapped part 271 303 if (mEnd) 272 memcpy(data + mEnd, mData, mEnd * sizeof(unsigned long));304 memcpy(data + (mLength - mEnd), mData, mEnd * sizeof(unsigned long)); 273 305 } 274 306 else -
trunk/src/VBox/Main/PerformanceImpl.cpp
r10779 r10868 202 202 ComSafeArrayOut (IPerformanceMetric *, outMetrics)) 203 203 { 204 LogFlowThisFuncEnter(); 204 205 //LogFlowThisFunc (("mState=%d, mType=%d\n", mState, mType)); 205 206 … … 234 235 } 235 236 retMetrics.detachTo (ComSafeArrayOutArg(outMetrics)); 237 LogFlowThisFuncLeave(); 236 238 return rc; 237 239 } … … 271 273 ComSafeArrayInArg (objects)); 272 274 273 /// @todo (r=dmik) why read lock below? individual elements get modified! 274 275 AutoReadLock alock (this); /* Need a read lock to access mBaseMetrics */ 276 /* Write lock is not needed since we are */ 277 /* fiddling with enable bit only. No harm */ 278 /* the readers may see it differently. */ 275 AutoWriteLock alock (this); /* Write lock is not needed atm since we are */ 276 /* fiddling with enable bit only, but we */ 277 /* care for those who come next :-). */ 279 278 280 279 BaseMetricList::iterator it; … … 296 295 ComSafeArrayInArg (objects)); 297 296 298 /// @todo (r=dmik) why read lock below? individual elements get modified! 299 300 AutoReadLock alock (this); /* Need a read lock to access mBaseMetrics */ 301 /* Write lock is not needed since we are */ 302 /* fiddling with enable bit only. No harm */ 303 /* the readers may see it differently. */ 297 AutoWriteLock alock (this); /* Write lock is not needed atm since we are */ 298 /* fiddling with enable bit only, but we */ 299 /* care for those who come next :-). */ 304 300 305 301 BaseMetricList::iterator it; … … 323 319 CheckComRCReturnRC (autoCaller.rc()); 324 320 321 pm::Filter filter (ComSafeArrayInArg (metricNames), 322 ComSafeArrayInArg (objects)); 323 325 324 AutoReadLock alock (this); 326 325 327 int i;328 MetricList::const_iterator it;329 326 /* Let's compute the size of the resulting flat array */ 330 size_t flatSize = 0, numberOfMetrics = 0; 327 size_t flatSize = 0; 328 MetricList filteredMetrics; 329 MetricList::iterator it; 331 330 for (it = m.metrics.begin(); it != m.metrics.end(); ++it) 332 { 333 /* @todo Filtering goes here! */ 334 flatSize += (*it)->getLength(); 335 ++numberOfMetrics; 336 } 331 if (filter.match ((*it)->getObject(), (*it)->getName())) 332 { 333 filteredMetrics.push_back (*it); 334 flatSize += (*it)->getLength(); 335 } 336 337 int i = 0; 337 338 size_t flatIndex = 0; 339 size_t numberOfMetrics = filteredMetrics.size(); 338 340 com::SafeArray <BSTR> retNames (numberOfMetrics); 339 341 com::SafeIfaceArray <IUnknown> retObjects (numberOfMetrics); … … 342 344 com::SafeArray <LONG> retData (flatSize); 343 345 344 for (it = m.metrics.begin(), i = 0; it != m.metrics.end(); ++it)346 for (it = filteredMetrics.begin(); it != filteredMetrics.end(); ++it, ++i) 345 347 { 346 348 /* @todo Filtering goes here! */ … … 354 356 retLengths[i] = length; 355 357 retIndices[i] = flatIndex; 356 ++i;357 358 flatIndex += length; 358 359 } … … 371 372 void PerformanceCollector::registerBaseMetric (pm::BaseMetric *baseMetric) 372 373 { 374 LogFlowThisFuncEnter(); 373 375 AutoCaller autoCaller (this); 374 376 if (!SUCCEEDED (autoCaller.rc())) return; 375 377 376 378 AutoWriteLock alock (this); 379 LogFlowThisFunc (("obj=%p name=%s\n", baseMetric->getObject(), baseMetric->getName())); 377 380 m.baseMetrics.push_back (baseMetric); 381 LogFlowThisFuncLeave(); 378 382 } 379 383 380 384 void PerformanceCollector::registerMetric (pm::Metric *metric) 381 385 { 386 LogFlowThisFuncEnter(); 382 387 AutoCaller autoCaller (this); 383 388 if (!SUCCEEDED (autoCaller.rc())) return; 384 389 385 390 AutoWriteLock alock (this); 391 LogFlowThisFunc (("obj=%p name=%s\n", metric->getObject(), metric->getName())); 386 392 m.metrics.push_back (metric); 393 LogFlowThisFuncLeave(); 387 394 } 388 395 389 396 void PerformanceCollector::unregisterBaseMetricsFor (const ComPtr <IUnknown> &aObject) 390 397 { 398 LogFlowThisFuncEnter(); 391 399 AutoCaller autoCaller (this); 392 400 if (!SUCCEEDED (autoCaller.rc())) return; 393 401 394 402 AutoWriteLock alock (this); 395 std::remove_if (m.baseMetrics.begin(), m.baseMetrics.end(), 396 std::bind2nd (std::mem_fun (&pm::BaseMetric::associatedWith), 397 aObject)); 403 LogFlowThisFunc (("before remove_if: m.baseMetrics.size()=%d, obj=%p\n", m.baseMetrics.size(), aObject)); 404 BaseMetricList::iterator it = std::remove_if ( 405 m.baseMetrics.begin(), m.baseMetrics.end(), std::bind2nd ( 406 std::mem_fun (&pm::BaseMetric::associatedWith), aObject)); 407 m.baseMetrics.erase(it, m.baseMetrics.end()); 408 LogFlowThisFunc (("after remove_if: m.baseMetrics.size()=%d\n", m.baseMetrics.size())); 409 LogFlowThisFuncLeave(); 398 410 } 399 411 400 412 void PerformanceCollector::unregisterMetricsFor (const ComPtr <IUnknown> &aObject) 401 413 { 414 LogFlowThisFuncEnter(); 402 415 AutoCaller autoCaller (this); 403 416 if (!SUCCEEDED (autoCaller.rc())) return; 404 417 405 418 AutoWriteLock alock (this); 406 std::remove_if (m.metrics.begin(), m.metrics.end(), 407 std::bind2nd (std::mem_fun (&pm::Metric::associatedWith), 408 aObject)); 419 LogFlowThisFunc (("obj=%p\n", aObject)); 420 MetricList::iterator it = std::remove_if ( 421 m.metrics.begin(), m.metrics.end(), std::bind2nd ( 422 std::mem_fun (&pm::Metric::associatedWith), aObject)); 423 m.metrics.erase(it, m.metrics.end()); 424 LogFlowThisFuncLeave(); 409 425 } 410 426 … … 427 443 void PerformanceCollector::samplerCallback() 428 444 { 445 LogFlowThisFuncEnter(); 429 446 AutoWriteLock alock (this); 430 447 … … 433 450 std::bind2nd (std::mem_fun (&pm::BaseMetric::collectorBeat), 434 451 timestamp)); 452 LogFlowThisFuncLeave(); 435 453 } 436 454 -
trunk/src/VBox/Main/include/MachineImpl.h
r10797 r10868 719 719 720 720 #ifdef VBOX_WITH_RESOURCE_USAGE_API 721 void registerMetrics (PerformanceCollector *aCollector );721 void registerMetrics (PerformanceCollector *aCollector, RTPROCESS pid); 722 722 void unregisterMetrics (PerformanceCollector *aCollector); 723 723 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ -
trunk/src/VBox/Main/include/Performance.h
r10770 r10868 72 72 virtual int getProcessMemoryUsage(RTPROCESS process, unsigned long *used) = 0; 73 73 74 virtual int getRawHostCpuLoad(u nsigned long *user, unsigned long *kernel, unsigned long*idle);75 virtual int getRawProcessCpuLoad(RTPROCESS process, u nsigned long *user, unsigned long *kernel);74 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); 75 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); 76 76 }; 77 77 … … 137 137 void collect(); 138 138 private: 139 u nsigned longmUserPrev;140 u nsigned longmKernelPrev;141 u nsigned longmIdlePrev;139 uint64_t mUserPrev; 140 uint64_t mKernelPrev; 141 uint64_t mIdlePrev; 142 142 }; 143 143 … … 199 199 void collect(); 200 200 private: 201 u nsigned longmHostTotalPrev;202 u nsigned longmProcessUserPrev;203 u nsigned longmProcessKernelPrev;201 uint64_t mHostTotalPrev; 202 uint64_t mProcessUserPrev; 203 uint64_t mProcessKernelPrev; 204 204 }; 205 205 … … 305 305 public: 306 306 MetricFactorySolaris(); 307 virtual BaseMetric *createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle); 308 virtual BaseMetric *createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel); 307 // Nothing else to do here (yet) 309 308 }; 310 309 … … 313 312 public: 314 313 MetricFactoryLinux(); 315 virtual BaseMetric *createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle); 316 virtual BaseMetric *createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel); 314 // Nothing else to do here (yet) 317 315 }; 318 316 -
trunk/src/VBox/Main/linux/PerformanceLinux.cpp
r10754 r10868 37 37 virtual int getProcessMemoryUsage(RTPROCESS process, unsigned long *used); 38 38 39 virtual int getRawHostCpuLoad(u nsigned long *user, unsigned long *kernel, unsigned long*idle);40 virtual int getRawProcessCpuLoad(RTPROCESS process, u nsigned long *user, unsigned long *kernel);39 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); 40 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); 41 41 }; 42 42 … … 49 49 } 50 50 51 BaseMetric *MetricFactoryLinux::createHostCpuLoad(ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle)52 {53 Assert(mHAL);54 return new HostCpuLoadRaw(mHAL, object, user, kernel, idle);55 }56 57 BaseMetric *MetricFactoryLinux::createMachineCpuLoad(ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel)58 {59 Assert(mHAL);60 return new MachineCpuLoadRaw(mHAL, object, process, user, kernel);61 }62 63 51 // Collector HAL for Linux 64 52 65 int CollectorLinux::getRawHostCpuLoad(u nsigned long *user, unsigned long *kernel, unsigned long*idle)53 int CollectorLinux::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle) 66 54 { 67 55 int rc = VINF_SUCCESS; 68 unsigned long nice;56 unsigned long u32user, u32nice, u32kernel, u32idle; 69 57 FILE *f = fopen("/proc/stat", "r"); 70 58 71 59 if (f) 72 60 { 73 if (fscanf(f, "cpu %lu %lu %lu %lu", user, &nice, kernel, idle) == 4) 74 *user += nice; 61 if (fscanf(f, "cpu %lu %lu %lu %lu", &u32user, &u32nice, &u32kernel, &u32idle) == 4) 62 { 63 *user = (uint64_t)u32user + u32nice; 64 *kernel = u32kernel; 65 *idle = u32idle; 66 } 75 67 else 76 68 rc = VERR_FILE_IO_ERROR; … … 83 75 } 84 76 85 int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, u nsigned long *user, unsigned long *kernel)77 int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total) 86 78 { 87 79 int rc = VINF_SUCCESS; … … 91 83 int iTmp; 92 84 unsigned uTmp; 93 unsigned long ulTmp ;85 unsigned long ulTmp, u32user, u32kernel; 94 86 char buf[80]; /* @todo: this should be tied to max allowed proc name. */ 87 88 uint64_t uHostUser, uHostKernel, uHostIdle; 89 rc = getRawHostCpuLoad(uHostUser, uHostKernel, uHostIdle); 90 if (RT_FAILURE(rc)) 91 return rc; 92 *total = (uint64_t)uHostUser + uHostKernel + uHostIdle; 95 93 96 94 RTStrAPrintf(&pszName, "/proc/%d/stat", process); … … 103 101 if (fscanf(f, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu", 104 102 &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp, 105 &ulTmp, &ulTmp, &ulTmp, &ulTmp, user,kernel) == 15)103 &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel) == 15) 106 104 { 107 105 Assert((pid_t)process == pid2); 106 *user = u32user; 107 *kernel = u32kernel; 108 108 } 109 109 else -
trunk/src/VBox/Main/testcase/Makefile.kmk
r10056 r10868 68 68 tstAPI_DEPS = $(VBOX_PATH_SDK)/include/VirtualBox_XPCOM.h 69 69 endif 70 ifdef VBOX_WITH_RESOURCE_USAGE_API 71 tstAPI_DEFS += VBOX_WITH_RESOURCE_USAGE_API 72 endif 70 73 71 74 -
trunk/src/VBox/Main/testcase/tstAPI.cpp
r10783 r10868 926 926 #endif 927 927 928 #if 1928 #ifdef VBOX_WITH_RESOURCE_USAGE_API 929 929 do { 930 930 // Get collector … … 948 948 printf ("Getting a machine object named '%ls'...\n", name.raw()); 949 949 CHECK_RC_BREAK (virtualBox->FindMachine (name, machine.asOutParam())); 950 951 // Setup base metrics952 com::SafeIfaceArray<IUnknown> objects(2);953 host.queryInterfaceTo(&objects[0]);954 machine.queryInterfaceTo(&objects[1]);955 CHECK_ERROR_BREAK (collector, SetupMetrics(ComSafeArrayAsInParam(baseMetrics),956 ComSafeArrayAsInParam(objects), 1u, 10u) );957 950 958 951 // Open session … … 969 962 CHECK_RC_BREAK (session->COMGETTER(Machine) (sessionMachine.asOutParam())); 970 963 964 // Setup base metrics 965 // Note that one needs to set up metrics after a session is open for a machine. 966 com::SafeIfaceArray<IUnknown> objects(2); 967 host.queryInterfaceTo(&objects[0]); 968 sessionMachine.queryInterfaceTo(&objects[1]); 969 CHECK_ERROR_BREAK (collector, SetupMetrics(ComSafeArrayAsInParam(baseMetrics), 970 ComSafeArrayAsInParam(objects), 1u, 10u) ); 971 971 972 // Get console 972 973 ComPtr <IConsole> console; … … 984 985 CHECK_RC (console->Pause()); 985 986 986 RTThreadSleep( 3000); // Sleep for 10 seconds987 RTThreadSleep(10000); // Sleep for 10 seconds 987 988 988 989 printf("Metrics collected with DSL machine paused: ---------------------\n"); … … 997 998 session->Close(); 998 999 } while (false); 999 #endif 1000 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 1000 1001 1001 1002 printf ("Press enter to release Session and VirtualBox instances..."); … … 1017 1018 } 1018 1019 1019 #if 11020 #ifdef VBOX_WITH_RESOURCE_USAGE_API 1020 1021 void queryMetrics (ComPtr <IPerformanceCollector> collector, 1021 1022 ComSafeArrayIn (IUnknown *, objects)) … … 1023 1024 HRESULT rc; 1024 1025 1025 Bstr metricNames[] = { L"CPU/Load/User:avg,CPU/Load/System:avg,CPU/Load/Idle:avg,RAM/Usage/Total,RAM/Usage/Used:avg" }; 1026 //Bstr metricNames[] = { L"CPU/Load/User:avg,CPU/Load/System:avg,CPU/Load/Idle:avg,RAM/Usage/Total,RAM/Usage/Used:avg" }; 1027 Bstr metricNames[] = { L"*" }; 1026 1028 com::SafeArray<BSTR> metrics (1); 1027 1029 metricNames[0].cloneTo (&metrics [0]); … … 1063 1065 } 1064 1066 } 1065 #endif 1067 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ -
trunk/src/VBox/Main/win/PerformanceWin.cpp
r10753 r10868 22 22 */ 23 23 24 #include <pdh.h> 25 #include <pdhmsg.h> 24 #include <Wbemidl.h> 26 25 #include <iprt/err.h> 27 26 27 #include "Logging.h" 28 28 #include "Performance.h" 29 30 //#pragma comment(lib, "pdh.lib")31 29 32 30 namespace pm { … … 44 42 virtual int getProcessMemoryUsage(RTPROCESS process, unsigned long *used); 45 43 44 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); 45 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); 46 46 private: 47 int convertPdhStatusToRTErr(PDH_STATUS pdhStatus); 48 HCOUNTER addCounter(HQUERY hQuery, LPCTSTR name); 49 int getCounterValue(HCOUNTER hCounter, DWORD flags, unsigned long *value); 50 51 HQUERY mHostCpuLoadQuery; 52 HCOUNTER mHostCpuLoadUserCounter; 53 HCOUNTER mHostCpuLoadKernelCounter; 54 HCOUNTER mHostCpuLoadIdleCounter; 47 long getPropertyHandle(IWbemObjectAccess *objAccess, LPCWSTR name); 48 int getObjects(IWbemHiPerfEnum *mEnum, IWbemObjectAccess ***objArray, DWORD *numReturned); 49 50 IWbemRefresher *mRefresher; 51 IWbemServices *mNameSpace; 52 53 IWbemHiPerfEnum *mEnumProcessor; 54 long mEnumProcessorID; 55 long mHostCpuLoadNameHandle; 56 long mHostCpuLoadUserHandle; 57 long mHostCpuLoadKernelHandle; 58 long mHostCpuLoadIdleHandle; 59 60 IWbemHiPerfEnum *mEnumProcess; 61 long mEnumProcessID; 62 long mProcessPIDHandle; 63 long mProcessCpuLoadUserHandle; 64 long mProcessCpuLoadKernelHandle; 65 long mProcessCpuLoadTimestampHandle; 66 long mProcessMemoryUsedHandle; 55 67 }; 56 68 … … 61 73 } 62 74 63 CollectorWin::CollectorWin() : mHostCpuLoadQuery(0) 64 { 65 PDH_STATUS pdhStatus; 66 67 pdhStatus = PdhOpenQuery(NULL, NULL, &mHostCpuLoadQuery); 68 if (pdhStatus != ERROR_SUCCESS) 75 CollectorWin::CollectorWin() : mRefresher(0), mNameSpace(0), mEnumProcessor(0), mEnumProcess(0) 76 { 77 HRESULT hr = S_OK; 78 IWbemConfigureRefresher *pConfig = NULL; 79 IWbemLocator *pWbemLocator = NULL; 80 BSTR bstrNameSpace = NULL; 81 82 if (SUCCEEDED (hr = CoCreateInstance( 83 CLSID_WbemLocator, 84 NULL, 85 CLSCTX_INPROC_SERVER, 86 IID_IWbemLocator, 87 (void**) &pWbemLocator))) 88 { 89 // Connect to the desired namespace. 90 bstrNameSpace = SysAllocString(L"\\\\.\\root\\cimv2"); 91 if (bstrNameSpace) 92 { 93 hr = pWbemLocator->ConnectServer( 94 bstrNameSpace, 95 NULL, // User name 96 NULL, // Password 97 NULL, // Locale 98 0L, // Security flags 99 NULL, // Authority 100 NULL, // Wbem context 101 &mNameSpace); 102 } 103 pWbemLocator->Release(); 104 SysFreeString(bstrNameSpace); 105 } 106 107 if (FAILED (hr)) { 108 Log (("Failed to get namespace. HR = %x\n", hr)); 69 109 return; 70 71 mHostCpuLoadUserCounter = addCounter (mHostCpuLoadQuery, 72 L"\\Processor(_Total)\\% User Time"); 73 mHostCpuLoadKernelCounter = addCounter (mHostCpuLoadQuery, 74 L"\\Processor(_Total)\\% Privileged Time"); 75 mHostCpuLoadIdleCounter = addCounter (mHostCpuLoadQuery, 76 L"\\Processor(_Total)\\% Idle Time"); 110 } 111 112 if (SUCCEEDED (hr = CoCreateInstance( 113 CLSID_WbemRefresher, 114 NULL, 115 CLSCTX_INPROC_SERVER, 116 IID_IWbemRefresher, 117 (void**) &mRefresher))) 118 { 119 if (SUCCEEDED (hr = mRefresher->QueryInterface( 120 IID_IWbemConfigureRefresher, 121 (void **)&pConfig))) 122 { 123 // Add an enumerator to the refresher. 124 if (SUCCEEDED (hr = pConfig->AddEnum( 125 mNameSpace, 126 L"Win32_PerfRawData_PerfOS_Processor", 127 0, 128 NULL, 129 &mEnumProcessor, 130 &mEnumProcessorID))) 131 { 132 hr = pConfig->AddEnum( 133 mNameSpace, 134 L"Win32_PerfRawData_PerfProc_Process", 135 0, 136 NULL, 137 &mEnumProcess, 138 &mEnumProcessID); 139 } 140 pConfig->Release(); 141 } 142 } 143 144 145 if (FAILED (hr)) { 146 Log (("Failed to add enumerators. HR = %x\n", hr)); 147 return; 148 } 149 150 // Retrieve property handles 151 152 if (FAILED (hr = mRefresher->Refresh(0L))) 153 { 154 Log (("Refresher failed. HR = %x\n", hr)); 155 return; 156 } 157 158 IWbemObjectAccess **apEnumAccess = NULL; 159 DWORD dwNumReturned = 0; 160 161 if (RT_FAILURE(getObjects(mEnumProcessor, &apEnumAccess, &dwNumReturned))) 162 return; 163 164 mHostCpuLoadNameHandle = getPropertyHandle(apEnumAccess[0], L"Name"); 165 mHostCpuLoadUserHandle = getPropertyHandle(apEnumAccess[0], L"PercentUserTime"); 166 mHostCpuLoadKernelHandle = getPropertyHandle(apEnumAccess[0], L"PercentPrivilegedTime"); 167 mHostCpuLoadIdleHandle = getPropertyHandle(apEnumAccess[0], L"PercentProcessorTime"); 168 169 delete [] apEnumAccess; 170 171 if (RT_FAILURE(getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned))) 172 return; 173 174 mProcessPIDHandle = getPropertyHandle(apEnumAccess[0], L"IDProcess"); 175 mProcessCpuLoadUserHandle = getPropertyHandle(apEnumAccess[0], L"PercentUserTime"); 176 mProcessCpuLoadKernelHandle = getPropertyHandle(apEnumAccess[0], L"PercentPrivilegedTime"); 177 mProcessCpuLoadTimestampHandle = getPropertyHandle(apEnumAccess[0], L"Timestamp_Sys100NS"); 178 mProcessMemoryUsedHandle = getPropertyHandle(apEnumAccess[0], L"WorkingSet"); 179 180 delete [] apEnumAccess; 77 181 } 78 182 79 183 CollectorWin::~CollectorWin() 80 184 { 81 if (mHostCpuLoadQuery) 82 PdhCloseQuery (mHostCpuLoadQuery); 83 } 84 85 int CollectorWin::convertPdhStatusToRTErr(PDH_STATUS pdhStatus) 86 { 87 switch (pdhStatus) 88 { 89 case PDH_INVALID_ARGUMENT: 90 return VERR_INVALID_PARAMETER; 91 case PDH_INVALID_HANDLE: 92 return VERR_INVALID_HANDLE; 93 } 94 95 return RTErrConvertFromWin32(pdhStatus); 96 } 97 98 HCOUNTER CollectorWin::addCounter(HQUERY hQuery, LPCTSTR name) 99 { 100 PDH_STATUS pdhStatus; 101 HCOUNTER hCounter; 102 103 pdhStatus = PdhAddCounter (hQuery, name, 0, &hCounter); 104 if (pdhStatus != ERROR_SUCCESS) 105 return 0; 106 return hCounter; 107 } 108 109 int CollectorWin::getCounterValue(HCOUNTER hCounter, DWORD flags, unsigned long *value) 110 { 111 PDH_STATUS pdhStatus; 112 PDH_FMT_COUNTERVALUE fmtValue; 113 114 pdhStatus = PdhGetFormattedCounterValue (hCounter, 115 PDH_FMT_LONG | flags, 116 NULL, 117 &fmtValue); 118 if (pdhStatus != ERROR_SUCCESS) 119 return convertPdhStatusToRTErr(pdhStatus); 120 121 *value = fmtValue.longValue; 122 185 if (NULL != mNameSpace) 186 { 187 mNameSpace->Release(); 188 } 189 if (NULL != mEnumProcessor) 190 { 191 mEnumProcessor->Release(); 192 } 193 if (NULL != mEnumProcess) 194 { 195 mEnumProcess->Release(); 196 } 197 if (NULL != mRefresher) 198 { 199 mRefresher->Release(); 200 } 201 } 202 203 long CollectorWin::getPropertyHandle(IWbemObjectAccess *objAccess, LPCWSTR name) 204 { 205 HRESULT hr; 206 CIMTYPE tmp; 207 long handle; 208 209 if (FAILED (hr = objAccess->GetPropertyHandle( 210 name, 211 &tmp, 212 &handle))) 213 { 214 Log (("Failed to get property handle for '%ls'. HR = %x\n", name, hr)); 215 return 0; /// @todo use throw 216 } 217 218 return handle; 219 } 220 221 int CollectorWin::getObjects(IWbemHiPerfEnum *mEnum, IWbemObjectAccess ***objArray, DWORD *numReturned) 222 { 223 HRESULT hr; 224 DWORD dwNumObjects = 0; 225 226 *objArray = NULL; 227 *numReturned = 0; 228 hr = mEnum->GetObjects(0L, dwNumObjects, *objArray, numReturned); 229 230 // If the buffer was not big enough, 231 // allocate a bigger buffer and retry. 232 if (hr == WBEM_E_BUFFER_TOO_SMALL 233 && *numReturned > dwNumObjects) 234 { 235 *objArray = new IWbemObjectAccess*[*numReturned]; 236 if (NULL == *objArray) 237 { 238 Log (("Could not allocate enumerator access objects\n")); 239 return VERR_NO_MEMORY; 240 } 241 242 SecureZeroMemory(*objArray, 243 *numReturned*sizeof(IWbemObjectAccess*)); 244 dwNumObjects = *numReturned; 245 246 if (FAILED (hr = mEnum->GetObjects(0L, 247 dwNumObjects, *objArray, numReturned))) 248 { 249 delete [] objArray; 250 Log (("Failed to get objects from enumerator. HR = %x\n", hr)); 251 return VERR_INTERNAL_ERROR; 252 } 253 } 254 else if (FAILED (hr)) 255 { 256 Log (("Failed to get objects from enumerator. HR = %x\n", hr)); 257 return VERR_INTERNAL_ERROR; 258 } 259 123 260 return VINF_SUCCESS; 124 261 } … … 126 263 int CollectorWin::getHostCpuLoad(unsigned long *user, unsigned long *kernel, unsigned long *idle) 127 264 { 128 int rc; 129 PDH_STATUS pdhStatus; 130 131 pdhStatus = PdhCollectQueryData (mHostCpuLoadQuery); 132 if (pdhStatus != ERROR_SUCCESS) 133 return convertPdhStatusToRTErr(pdhStatus); 134 135 rc = getCounterValue (mHostCpuLoadUserCounter, PDH_FMT_1000, user); 136 AssertRCReturn(rc, rc); 137 138 rc = getCounterValue (mHostCpuLoadKernelCounter, PDH_FMT_1000, kernel); 139 AssertRCReturn(rc, rc); 140 141 rc = getCounterValue (mHostCpuLoadIdleCounter, PDH_FMT_1000, idle); 142 AssertRCReturn(rc, rc); 143 144 return VINF_SUCCESS; 265 return VERR_NOT_IMPLEMENTED; 266 } 267 268 int CollectorWin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle) 269 { 270 HRESULT hr; 271 IWbemObjectAccess **apEnumAccess = NULL; 272 DWORD dwNumReturned = 0; 273 274 LogFlowThisFuncEnter(); 275 276 if (FAILED (hr = mRefresher->Refresh(0L))) 277 { 278 Log (("Refresher failed. HR = %x\n", hr)); 279 return VERR_INTERNAL_ERROR; 280 } 281 282 int rc = getObjects(mEnumProcessor, &apEnumAccess, &dwNumReturned); 283 if (RT_FAILURE(rc)) 284 return rc; 285 286 for (unsigned i = 0; i < dwNumReturned; i++) 287 { 288 long bytesRead = 0; 289 WCHAR tmpBuf[200]; 290 291 if (FAILED (hr = apEnumAccess[i]->ReadPropertyValue( 292 mHostCpuLoadNameHandle, 293 sizeof(tmpBuf), 294 &bytesRead, 295 (byte*)tmpBuf))) 296 { 297 Log (("Failed to read 'Name' property. HR = %x\n", hr)); 298 return VERR_INTERNAL_ERROR; 299 } 300 if (wcscmp(tmpBuf, L"_Total") == 0) 301 { 302 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 303 mHostCpuLoadUserHandle, 304 user))) 305 { 306 Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr)); 307 return VERR_INTERNAL_ERROR; 308 } 309 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 310 mHostCpuLoadKernelHandle, 311 kernel))) 312 { 313 Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr)); 314 return VERR_INTERNAL_ERROR; 315 } 316 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 317 mHostCpuLoadIdleHandle, 318 idle))) 319 { 320 Log (("Failed to read 'PercentProcessorTime' property. HR = %x\n", hr)); 321 return VERR_INTERNAL_ERROR; 322 } 323 rc = VINF_SUCCESS; 324 } 325 apEnumAccess[i]->Release(); 326 apEnumAccess[i] = NULL; 327 } 328 delete [] apEnumAccess; 329 330 LogFlowThisFunc(("user=%lu kernel=%lu idle=%lu\n", *user, *kernel, *idle)); 331 LogFlowThisFuncLeave(); 332 333 return rc; 145 334 } 146 335 147 336 int CollectorWin::getHostCpuMHz(unsigned long *mhz) 148 337 { 149 return E_NOTIMPL;338 return VERR_NOT_IMPLEMENTED; 150 339 } 151 340 … … 169 358 int CollectorWin::getProcessCpuLoad(RTPROCESS process, unsigned long *user, unsigned long *kernel) 170 359 { 171 return E_NOTIMPL; 360 return VERR_NOT_IMPLEMENTED; 361 } 362 363 int CollectorWin::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total) 364 { 365 HRESULT hr; 366 IWbemObjectAccess **apEnumAccess = NULL; 367 DWORD dwNumReturned = 0; 368 369 LogFlowThisFuncEnter(); 370 371 if (FAILED (hr = mRefresher->Refresh(0L))) 372 { 373 Log (("Refresher failed. HR = %x\n", hr)); 374 return VERR_INTERNAL_ERROR; 375 } 376 377 int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned); 378 if (RT_FAILURE(rc)) 379 return rc; 380 381 rc = VERR_NOT_FOUND; 382 383 for (unsigned i = 0; i < dwNumReturned; i++) 384 { 385 DWORD dwIDProcess; 386 387 if (FAILED (hr = apEnumAccess[i]->ReadDWORD( 388 mProcessPIDHandle, 389 &dwIDProcess))) 390 { 391 Log (("Failed to read 'IDProcess' property. HR = %x\n", hr)); 392 return VERR_INTERNAL_ERROR; 393 } 394 LogFlowThisFunc (("Matching machine process %x against %x...\n", process, dwIDProcess)); 395 if (dwIDProcess == process) 396 { 397 LogFlowThisFunc (("Match found.\n")); 398 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 399 mProcessCpuLoadUserHandle, 400 user))) 401 { 402 Log (("Failed to read 'PercentUserTime' property. HR = %x\n", hr)); 403 return VERR_INTERNAL_ERROR; 404 } 405 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 406 mProcessCpuLoadKernelHandle, 407 kernel))) 408 { 409 Log (("Failed to read 'PercentPrivilegedTime' property. HR = %x\n", hr)); 410 return VERR_INTERNAL_ERROR; 411 } 412 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 413 mProcessCpuLoadTimestampHandle, 414 total))) 415 { 416 Log (("Failed to read 'Timestamp_Sys100NS' property. HR = %x\n", hr)); 417 return VERR_INTERNAL_ERROR; 418 } 419 rc = VINF_SUCCESS; 420 } 421 apEnumAccess[i]->Release(); 422 apEnumAccess[i] = NULL; 423 } 424 delete [] apEnumAccess; 425 426 LogFlowThisFunc(("user=%lu kernel=%lu total=%lu\n", *user, *kernel, *total)); 427 LogFlowThisFuncLeave(); 428 429 return rc; 172 430 } 173 431 174 432 int CollectorWin::getProcessMemoryUsage(RTPROCESS process, unsigned long *used) 175 433 { 176 return E_NOTIMPL; 177 } 178 179 } 434 HRESULT hr; 435 IWbemObjectAccess **apEnumAccess = NULL; 436 DWORD dwNumReturned = 0; 437 438 LogFlowThisFuncEnter(); 439 440 if (FAILED (hr = mRefresher->Refresh(0L))) 441 { 442 Log (("Refresher failed. HR = %x\n", hr)); 443 return VERR_INTERNAL_ERROR; 444 } 445 446 int rc = getObjects(mEnumProcess, &apEnumAccess, &dwNumReturned); 447 if (RT_FAILURE(rc)) 448 return rc; 449 450 rc = VERR_NOT_FOUND; 451 452 for (unsigned i = 0; i < dwNumReturned; i++) 453 { 454 DWORD dwIDProcess; 455 456 if (FAILED (hr = apEnumAccess[i]->ReadDWORD( 457 mProcessPIDHandle, 458 &dwIDProcess))) 459 { 460 Log (("Failed to read 'IDProcess' property. HR = %x\n", hr)); 461 return VERR_INTERNAL_ERROR; 462 } 463 if (dwIDProcess == process) 464 { 465 uint64_t u64used = 0; 466 467 if (FAILED (hr = apEnumAccess[i]->ReadQWORD( 468 mProcessMemoryUsedHandle, 469 &u64used))) 470 { 471 Log (("Failed to read 'WorkingSet' property. HR = %x\n", hr)); 472 return VERR_INTERNAL_ERROR; 473 } 474 *used = (unsigned long)(u64used / 1024); 475 rc = VINF_SUCCESS; 476 } 477 apEnumAccess[i]->Release(); 478 apEnumAccess[i] = NULL; 479 } 480 delete [] apEnumAccess; 481 482 LogFlowThisFunc(("used=%lu\n", *used)); 483 LogFlowThisFuncLeave(); 484 485 return rc; 486 } 487 488 } -
trunk/src/VBox/Main/win/svcmain.cpp
r8155 r10868 173 173 #endif 174 174 _ASSERTE(SUCCEEDED(hRes)); 175 /* 176 * Need to initialize security to access performance enumerators. 177 */ 178 hRes = CoInitializeSecurity( 179 NULL, 180 -1, 181 NULL, 182 NULL, 183 RPC_C_AUTHN_LEVEL_NONE, 184 RPC_C_IMP_LEVEL_IMPERSONATE, 185 NULL, EOAC_NONE, 0); 186 _ASSERTE(SUCCEEDED(hRes)); 175 187 _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox); 176 188 _Module.dwThreadID = GetCurrentThreadId();
Note:
See TracChangeset
for help on using the changeset viewer.