1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/perftests/measurements.h"
6
7 #include <stdint.h>
8
9 #include "base/logging.h"
10 #include "testing/perf/perf_result_reporter.h"
11 #include "ui/gl/gpu_timing.h"
12
13 namespace gpu {
14
15 Measurement::Measurement() = default;
16 Measurement::Measurement(const Measurement& m) = default;
Measurement(const std::string & metric_basename,const base::TimeDelta wall_time,const base::TimeDelta cpu_time,const base::TimeDelta gpu_time)17 Measurement::Measurement(const std::string& metric_basename,
18 const base::TimeDelta wall_time,
19 const base::TimeDelta cpu_time,
20 const base::TimeDelta gpu_time)
21 : metric_basename(metric_basename),
22 wall_time(wall_time),
23 cpu_time(cpu_time),
24 gpu_time(gpu_time) {}
25
PrintResult(const std::string & story) const26 void Measurement::PrintResult(const std::string& story) const {
27 auto reporter =
28 std::make_unique<perf_test::PerfResultReporter>(metric_basename, story);
29 reporter->RegisterImportantMetric("_wall", "ms");
30 reporter->AddResult("_wall", wall_time.InMillisecondsF());
31 if (cpu_time.InMicroseconds() >= 0) {
32 reporter->RegisterImportantMetric("_cpu", "ms");
33 reporter->AddResult("_cpu", cpu_time.InMillisecondsF());
34 }
35 if (gpu_time.InMicroseconds() >= 0) {
36 reporter->RegisterImportantMetric("_gpu", "ms");
37 reporter->AddResult("_gpu", gpu_time.InMillisecondsF());
38 }
39 }
40
Increment(const Measurement & m)41 Measurement& Measurement::Increment(const Measurement& m) {
42 wall_time += m.wall_time;
43 cpu_time += m.cpu_time;
44 gpu_time += m.gpu_time;
45 return *this;
46 }
47
Divide(int a) const48 Measurement Measurement::Divide(int a) const {
49 return Measurement(metric_basename, wall_time / a, cpu_time / a,
50 gpu_time / a);
51 }
52
53 Measurement::~Measurement() = default;
54
MeasurementTimers(gl::GPUTimingClient * gpu_timing_client)55 MeasurementTimers::MeasurementTimers(gl::GPUTimingClient* gpu_timing_client)
56 : wall_time_start_(), cpu_time_start_(), gpu_timer_() {
57 DCHECK(gpu_timing_client);
58 wall_time_start_ = base::TimeTicks::Now();
59 if (base::ThreadTicks::IsSupported()) {
60 base::ThreadTicks::WaitUntilInitialized();
61 cpu_time_start_ = base::ThreadTicks::Now();
62 } else {
63 static bool logged_once = false;
64 LOG_IF(WARNING, !logged_once) << "ThreadTicks not supported.";
65 logged_once = true;
66 }
67
68 if (gpu_timing_client->IsAvailable()) {
69 gpu_timer_ = gpu_timing_client->CreateGPUTimer(true);
70 gpu_timer_->Start();
71 }
72 }
73
Record()74 void MeasurementTimers::Record() {
75 wall_time_ = base::TimeTicks::Now() - wall_time_start_;
76 if (base::ThreadTicks::IsSupported()) {
77 cpu_time_ = base::ThreadTicks::Now() - cpu_time_start_;
78 }
79 if (gpu_timer_.get()) {
80 gpu_timer_->End();
81 }
82 }
83
GetAsMeasurement(const std::string & metric_basename)84 Measurement MeasurementTimers::GetAsMeasurement(
85 const std::string& metric_basename) {
86 DCHECK_NE(base::TimeDelta(),
87 wall_time_); // At least wall_time_ has been set.
88
89 if (!base::ThreadTicks::IsSupported()) {
90 cpu_time_ = base::TimeDelta::FromMicroseconds(-1);
91 }
92 int64_t gpu_time = -1;
93 if (gpu_timer_.get() != nullptr && gpu_timer_->IsAvailable()) {
94 gpu_time = gpu_timer_->GetDeltaElapsed();
95 }
96 return Measurement(metric_basename, wall_time_, cpu_time_,
97 base::TimeDelta::FromMicroseconds(gpu_time));
98 }
99
~MeasurementTimers()100 MeasurementTimers::~MeasurementTimers() {
101 if (gpu_timer_.get()) {
102 gpu_timer_->Destroy(true);
103 }
104 }
105
106 } // namespace gpu
107