blob: 237e776506a207228523157727ef1e2064df542e [file] [log] [blame]
/*
* 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