Home | History | Annotate | Download | only in source
      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