xref: /aosp_15_r20/external/cronet/testing/perf/perf_result_reporter.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 The Chromium Authors
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 "testing/perf/perf_result_reporter.h"
6 
7 #include <ostream>
8 #include <vector>
9 
10 #include "base/check.h"
11 #include "base/containers/contains.h"
12 #include "base/no_destructor.h"
13 #include "base/notreached.h"
14 #include "testing/perf/perf_test.h"
15 
16 namespace {
17 
18 // These characters mess with either the stdout parsing or the dashboard itself.
19 static const base::NoDestructor<std::vector<std::string>> kInvalidCharacters{
20     {"/", ":", "="}};
21 
CheckForInvalidCharacters(const std::string & str)22 void CheckForInvalidCharacters(const std::string& str) {
23   for (const auto& invalid : *kInvalidCharacters) {
24     CHECK(!base::Contains(str, invalid))
25         << "Given invalid character for perf names '" << invalid << "'";
26   }
27 }
28 
29 }  // namespace
30 
31 namespace perf_test {
32 
PerfResultReporter(const std::string & metric_basename,const std::string & story_name)33 PerfResultReporter::PerfResultReporter(const std::string& metric_basename,
34                                        const std::string& story_name)
35     : metric_basename_(metric_basename), story_name_(story_name) {
36   CheckForInvalidCharacters(metric_basename_);
37   CheckForInvalidCharacters(story_name_);
38 }
39 
40 PerfResultReporter::~PerfResultReporter() = default;
41 
RegisterFyiMetric(const std::string & metric_suffix,const std::string & units)42 void PerfResultReporter::RegisterFyiMetric(const std::string& metric_suffix,
43                                            const std::string& units) {
44   RegisterMetric(metric_suffix, units, false);
45 }
46 
RegisterImportantMetric(const std::string & metric_suffix,const std::string & units)47 void PerfResultReporter::RegisterImportantMetric(
48     const std::string& metric_suffix,
49     const std::string& units) {
50   RegisterMetric(metric_suffix, units, true);
51 }
52 
AddResult(const std::string & metric_suffix,size_t value) const53 void PerfResultReporter::AddResult(const std::string& metric_suffix,
54                                    size_t value) const {
55   auto info = GetMetricInfoOrFail(metric_suffix);
56 
57   PrintResult(metric_basename_, metric_suffix, story_name_, value, info.units,
58               info.important);
59 }
60 
AddResult(const std::string & metric_suffix,double value) const61 void PerfResultReporter::AddResult(const std::string& metric_suffix,
62                                    double value) const {
63   auto info = GetMetricInfoOrFail(metric_suffix);
64 
65   PrintResult(metric_basename_, metric_suffix, story_name_, value, info.units,
66               info.important);
67 }
68 
AddResult(const std::string & metric_suffix,const std::string & value) const69 void PerfResultReporter::AddResult(const std::string& metric_suffix,
70                                    const std::string& value) const {
71   auto info = GetMetricInfoOrFail(metric_suffix);
72 
73   PrintResult(metric_basename_, metric_suffix, story_name_, value, info.units,
74               info.important);
75 }
76 
AddResult(const std::string & metric_suffix,base::TimeDelta value) const77 void PerfResultReporter::AddResult(const std::string& metric_suffix,
78                                    base::TimeDelta value) const {
79   auto info = GetMetricInfoOrFail(metric_suffix);
80 
81   // Decide what time unit to convert the TimeDelta into. Units are based on
82   // the legacy units in
83   // https://cs.chromium.org/chromium/src/third_party/catapult/tracing/tracing/value/legacy_unit_info.py?q=legacy_unit_info
84   double time = 0;
85   if (info.units == "seconds") {
86     time = value.InSecondsF();
87   } else if (info.units == "ms" || info.units == "milliseconds") {
88     time = value.InMillisecondsF();
89   } else if (info.units == "us") {
90     time = value.InMicrosecondsF();
91   } else if (info.units == "ns") {
92     time = value.InNanoseconds();
93   } else {
94     NOTREACHED() << "Attempted to use AddResult with a TimeDelta when "
95                  << "registered unit for metric " << metric_suffix << " is "
96                  << info.units;
97   }
98 
99   PrintResult(metric_basename_, metric_suffix, story_name_, time, info.units,
100               info.important);
101 }
102 
AddResultList(const std::string & metric_suffix,const std::string & values) const103 void PerfResultReporter::AddResultList(const std::string& metric_suffix,
104                                        const std::string& values) const {
105   auto info = GetMetricInfoOrFail(metric_suffix);
106 
107   PrintResultList(metric_basename_, metric_suffix, story_name_, values,
108                   info.units, info.important);
109 }
110 
AddResultMeanAndError(const std::string & metric_suffix,const std::string & mean_and_error)111 void PerfResultReporter::AddResultMeanAndError(
112     const std::string& metric_suffix,
113     const std::string& mean_and_error) {
114   auto info = GetMetricInfoOrFail(metric_suffix);
115 
116   PrintResultMeanAndError(metric_basename_, metric_suffix, story_name_,
117                           mean_and_error, info.units, info.important);
118 }
119 
GetMetricInfo(const std::string & metric_suffix,MetricInfo * out) const120 bool PerfResultReporter::GetMetricInfo(const std::string& metric_suffix,
121                                        MetricInfo* out) const {
122   auto iter = metric_map_.find(metric_suffix);
123   if (iter == metric_map_.end()) {
124     return false;
125   }
126 
127   *out = iter->second;
128   return true;
129 }
130 
RegisterMetric(const std::string & metric_suffix,const std::string & units,bool important)131 void PerfResultReporter::RegisterMetric(const std::string& metric_suffix,
132                                         const std::string& units,
133                                         bool important) {
134   CheckForInvalidCharacters(metric_suffix);
135   CHECK(metric_map_.count(metric_suffix) == 0);
136   metric_map_.insert({metric_suffix, {units, important}});
137 }
138 
GetMetricInfoOrFail(const std::string & metric_suffix) const139 MetricInfo PerfResultReporter::GetMetricInfoOrFail(
140     const std::string& metric_suffix) const {
141   MetricInfo info;
142   CHECK(GetMetricInfo(metric_suffix, &info))
143       << "Attempted to use unregistered metric " << metric_suffix;
144   return info;
145 }
146 
147 }  // namespace perf_test
148