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 16const int kCpuCheckPeriodMs = 100; 17 18namespace webrtc { 19 20CpuMeasurementHarness* 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 44CpuMeasurementHarness::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 58CpuMeasurementHarness::~CpuMeasurementHarness() { 59} 60 61bool 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 88int 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 97bool 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 110void 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 118bool 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