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
Create(CpuTarget * target,int work_period_ms,int work_iterations_per_period,int duration_ms)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
CpuMeasurementHarness(CpuTarget * target,int work_period_ms,int work_iterations_per_period,int duration_ms)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
~CpuMeasurementHarness()58 CpuMeasurementHarness::~CpuMeasurementHarness() {
59 }
60
Run()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
AverageCpu()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
WaitForCpuInit()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
Measure()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
DoWork()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