1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "system_wrappers/interface/cpu_wrapper.h" 12 #include "system_wrappers/interface/event_wrapper.h" 13 #include "system_wrappers/interface/scoped_ptr.h" 14 #include "system_wrappers/source/cpu_measurement_harness.h" 15 16 const int kCpuCheckPeriodMs = 100; 17 18 namespace webrtc { 19 20 CpuMeasurementHarness* CpuMeasurementHarness::Create( 21 CpuTarget* target, 22 int work_period_ms, 23 int work_iterations_per_period, 24 int duration_ms) { 25 if (target == NULL) { 26 return NULL; 27 } 28 if (work_period_ms > duration_ms) { 29 return NULL; 30 } 31 if (work_period_ms < 0) { 32 return NULL; 33 } 34 if (duration_ms < 0) { 35 return NULL; 36 } 37 if (work_iterations_per_period < 1) { 38 return NULL; 39 } 40 return new CpuMeasurementHarness(target, work_period_ms, 41 work_iterations_per_period, duration_ms); 42 } 43 44 CpuMeasurementHarness::CpuMeasurementHarness(CpuTarget* target, 45 int work_period_ms, 46 int work_iterations_per_period, 47 int duration_ms) 48 : cpu_target_(target), 49 work_period_ms_(work_period_ms), 50 work_iterations_per_period_(work_iterations_per_period), 51 duration_ms_(duration_ms), 52 cpu_sum_(0), 53 cpu_iterations_(0), 54 cpu_(CpuWrapper::CreateCpu()), 55 event_(EventWrapper::Create()) { 56 } 57 58 CpuMeasurementHarness::~CpuMeasurementHarness() { 59 } 60 61 bool CpuMeasurementHarness::Run() { 62 if (!WaitForCpuInit()) { 63 return false; 64 } 65 // No need for precision. Run for approximately the asked for duration. 66 // TODO(hellner): very low prio if at all, the actual duration of the test 67 // will be longer if calling DoWork() is not negligable and/or called many 68 // times. It may make sense to compensate for drift here. This will, 69 // however, only add complexity with minimal gains. Perhaps renaming the 70 // duration_ms_ to something more fuzzy is a better idea. However, the name 71 // would be very convoluted if it is to be self documenting. 72 int elapsed_time_ms = 0; 73 int last_measured_time = 0; 74 while (elapsed_time_ms < duration_ms_) { 75 if (((elapsed_time_ms - last_measured_time) / kCpuCheckPeriodMs) >= 1) { 76 last_measured_time = elapsed_time_ms; 77 Measure(); 78 } 79 if (!DoWork()) { 80 return false; 81 } 82 event_->Wait(work_period_ms_); 83 elapsed_time_ms += work_period_ms_; 84 } 85 return true; 86 } 87 88 int CpuMeasurementHarness::AverageCpu() { 89 if (cpu_iterations_ == 0) { 90 return 0; 91 } 92 assert(cpu_sum_ >= 0); 93 assert(cpu_iterations_ >= 0); 94 return cpu_sum_ / cpu_iterations_; 95 } 96 97 bool CpuMeasurementHarness::WaitForCpuInit() { 98 bool cpu_usage_available = false; 99 int num_iterations = 0; 100 // Initializing the CPU measurements may take a couple of seconds on Windows. 101 // Since the initialization is lazy we need to wait until it is completed. 102 // Should not take more than 10000 ms. 103 while (!cpu_usage_available && (++num_iterations < 10000)) { 104 event_->Wait(1); 105 cpu_usage_available = cpu_->CpuUsage() != -1; 106 } 107 return cpu_usage_available; 108 } 109 110 void CpuMeasurementHarness::Measure() { 111 WebRtc_UWord32 num_cores = 0; 112 WebRtc_UWord32* cores = NULL; 113 // Return the average CPU for now. 114 cpu_sum_ = cpu_->CpuUsageMultiCore(num_cores, cores); 115 ++cpu_iterations_; 116 } 117 118 bool CpuMeasurementHarness::DoWork() { 119 for (int i = 0; i < work_iterations_per_period_; ++i) { 120 if (!cpu_target_->DoWork()) { 121 return false; 122 } 123 } 124 return true; 125 } 126 127 } // namespace webrtc 128