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