| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "system_wrappers/interface/cpu_wrapper.h" |
| #include "system_wrappers/interface/event_wrapper.h" |
| #include "system_wrappers/interface/scoped_ptr.h" |
| #include "system_wrappers/source/cpu_measurement_harness.h" |
| |
| const int kCpuCheckPeriodMs = 100; |
| |
| namespace webrtc { |
| |
| CpuMeasurementHarness* CpuMeasurementHarness::Create( |
| CpuTarget* target, |
| int work_period_ms, |
| int work_iterations_per_period, |
| int duration_ms) { |
| if (target == NULL) { |
| return NULL; |
| } |
| if (work_period_ms > duration_ms) { |
| return NULL; |
| } |
| if (work_period_ms < 0) { |
| return NULL; |
| } |
| if (duration_ms < 0) { |
| return NULL; |
| } |
| if (work_iterations_per_period < 1) { |
| return NULL; |
| } |
| return new CpuMeasurementHarness(target, work_period_ms, |
| work_iterations_per_period, duration_ms); |
| } |
| |
| CpuMeasurementHarness::CpuMeasurementHarness(CpuTarget* target, |
| int work_period_ms, |
| int work_iterations_per_period, |
| int duration_ms) |
| : cpu_target_(target), |
| work_period_ms_(work_period_ms), |
| work_iterations_per_period_(work_iterations_per_period), |
| duration_ms_(duration_ms), |
| cpu_sum_(0), |
| cpu_iterations_(0), |
| cpu_(CpuWrapper::CreateCpu()), |
| event_(EventWrapper::Create()) { |
| } |
| |
| CpuMeasurementHarness::~CpuMeasurementHarness() { |
| } |
| |
| bool CpuMeasurementHarness::Run() { |
| if (!WaitForCpuInit()) { |
| return false; |
| } |
| // No need for precision. Run for approximately the asked for duration. |
| // TODO(hellner): very low prio if at all, the actual duration of the test |
| // will be longer if calling DoWork() is not negligable and/or called many |
| // times. It may make sense to compensate for drift here. This will, |
| // however, only add complexity with minimal gains. Perhaps renaming the |
| // duration_ms_ to something more fuzzy is a better idea. However, the name |
| // would be very convoluted if it is to be self documenting. |
| int elapsed_time_ms = 0; |
| int last_measured_time = 0; |
| while (elapsed_time_ms < duration_ms_) { |
| if (((elapsed_time_ms - last_measured_time) / kCpuCheckPeriodMs) >= 1) { |
| last_measured_time = elapsed_time_ms; |
| Measure(); |
| } |
| if (!DoWork()) { |
| return false; |
| } |
| event_->Wait(work_period_ms_); |
| elapsed_time_ms += work_period_ms_; |
| } |
| return true; |
| } |
| |
| int CpuMeasurementHarness::AverageCpu() { |
| if (cpu_iterations_ == 0) { |
| return 0; |
| } |
| assert(cpu_sum_ >= 0); |
| assert(cpu_iterations_ >= 0); |
| return cpu_sum_ / cpu_iterations_; |
| } |
| |
| bool CpuMeasurementHarness::WaitForCpuInit() { |
| bool cpu_usage_available = false; |
| int num_iterations = 0; |
| // Initializing the CPU measurements may take a couple of seconds on Windows. |
| // Since the initialization is lazy we need to wait until it is completed. |
| // Should not take more than 10000 ms. |
| while (!cpu_usage_available && (++num_iterations < 10000)) { |
| event_->Wait(1); |
| cpu_usage_available = cpu_->CpuUsage() != -1; |
| } |
| return cpu_usage_available; |
| } |
| |
| void CpuMeasurementHarness::Measure() { |
| WebRtc_UWord32 num_cores = 0; |
| WebRtc_UWord32* cores = NULL; |
| // Return the average CPU for now. |
| cpu_sum_ = cpu_->CpuUsageMultiCore(num_cores, cores); |
| ++cpu_iterations_; |
| } |
| |
| bool CpuMeasurementHarness::DoWork() { |
| for (int i = 0; i < work_iterations_per_period_; ++i) { |
| if (!cpu_target_->DoWork()) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| } // namespace webrtc |