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