1 // Copyright 2013 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 "perf_test.h"
6 
7 #include "common/third_party/base/anglebase/no_destructor.h"
8 
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <vector>
12 
13 namespace
14 {
15 
FormatString(const char * fmt,va_list vararg)16 std::string FormatString(const char *fmt, va_list vararg)
17 {
18     static angle::base::NoDestructor<std::vector<char>> buffer(512);
19 
20     // Attempt to just print to the current buffer
21     int len = vsnprintf(buffer->data(), buffer->size(), fmt, vararg);
22     if (len < 0 || static_cast<size_t>(len) >= buffer->size())
23     {
24         // Buffer was not large enough, calculate the required size and resize the buffer
25         len = vsnprintf(NULL, 0, fmt, vararg);
26         buffer->resize(len + 1);
27 
28         // Print again
29         vsnprintf(buffer->data(), buffer->size(), fmt, vararg);
30     }
31 
32     return std::string(buffer->data(), len);
33 }
34 
StringPrintf(const char * fmt,...)35 std::string StringPrintf(const char *fmt, ...)
36 {
37     va_list vararg;
38     va_start(vararg, fmt);
39     std::string result = FormatString(fmt, vararg);
40     va_end(vararg);
41     return result;
42 }
43 
NumberToString(size_t value)44 std::string NumberToString(size_t value)
45 {
46     return StringPrintf("%u", value);
47 }
48 
NumberToString(double value)49 std::string NumberToString(double value)
50 {
51     return StringPrintf("%.10lf", value);
52 }
53 
ResultsToString(const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & values,const std::string & prefix,const std::string & suffix,const std::string & units,bool important)54 std::string ResultsToString(const std::string &measurement,
55                             const std::string &modifier,
56                             const std::string &trace,
57                             const std::string &values,
58                             const std::string &prefix,
59                             const std::string &suffix,
60                             const std::string &units,
61                             bool important)
62 {
63     // <*>RESULT <graph_name>: <trace_name>= <value> <units>
64     // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units>
65     // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units>
66     return StringPrintf("%sRESULT %s%s: %s= %s%s%s %s\n", important ? "*" : "", measurement.c_str(),
67                         modifier.c_str(), trace.c_str(), prefix.c_str(), values.c_str(),
68                         suffix.c_str(), units.c_str());
69 }
70 
PrintResultsImpl(const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & values,const std::string & prefix,const std::string & suffix,const std::string & units,bool important)71 void PrintResultsImpl(const std::string &measurement,
72                       const std::string &modifier,
73                       const std::string &trace,
74                       const std::string &values,
75                       const std::string &prefix,
76                       const std::string &suffix,
77                       const std::string &units,
78                       bool important)
79 {
80     fflush(stdout);
81     printf("%s",
82            ResultsToString(measurement, modifier, trace, values, prefix, suffix, units, important)
83                .c_str());
84     fflush(stdout);
85 }
86 
87 }  // namespace
88 
89 namespace perf_test
90 {
91 
PrintResult(const std::string & measurement,const std::string & modifier,const std::string & trace,size_t value,const std::string & units,bool important)92 void PrintResult(const std::string &measurement,
93                  const std::string &modifier,
94                  const std::string &trace,
95                  size_t value,
96                  const std::string &units,
97                  bool important)
98 {
99     PrintResultsImpl(measurement, modifier, trace, NumberToString(value), std::string(),
100                      std::string(), units, important);
101 }
102 
PrintResult(const std::string & measurement,const std::string & modifier,const std::string & trace,double value,const std::string & units,bool important)103 void PrintResult(const std::string &measurement,
104                  const std::string &modifier,
105                  const std::string &trace,
106                  double value,
107                  const std::string &units,
108                  bool important)
109 {
110     PrintResultsImpl(measurement, modifier, trace, NumberToString(value), std::string(),
111                      std::string(), units, important);
112 }
113 
AppendResult(std::string & output,const std::string & measurement,const std::string & modifier,const std::string & trace,size_t value,const std::string & units,bool important)114 void AppendResult(std::string &output,
115                   const std::string &measurement,
116                   const std::string &modifier,
117                   const std::string &trace,
118                   size_t value,
119                   const std::string &units,
120                   bool important)
121 {
122     output += ResultsToString(measurement, modifier, trace, NumberToString(value), std::string(),
123                               std::string(), units, important);
124 }
125 
PrintResult(const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & value,const std::string & units,bool important)126 void PrintResult(const std::string &measurement,
127                  const std::string &modifier,
128                  const std::string &trace,
129                  const std::string &value,
130                  const std::string &units,
131                  bool important)
132 {
133     PrintResultsImpl(measurement, modifier, trace, value, std::string(), std::string(), units,
134                      important);
135 }
136 
AppendResult(std::string & output,const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & value,const std::string & units,bool important)137 void AppendResult(std::string &output,
138                   const std::string &measurement,
139                   const std::string &modifier,
140                   const std::string &trace,
141                   const std::string &value,
142                   const std::string &units,
143                   bool important)
144 {
145     output += ResultsToString(measurement, modifier, trace, value, std::string(), std::string(),
146                               units, important);
147 }
148 
PrintResultMeanAndError(const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & mean_and_error,const std::string & units,bool important)149 void PrintResultMeanAndError(const std::string &measurement,
150                              const std::string &modifier,
151                              const std::string &trace,
152                              const std::string &mean_and_error,
153                              const std::string &units,
154                              bool important)
155 {
156     PrintResultsImpl(measurement, modifier, trace, mean_and_error, "{", "}", units, important);
157 }
158 
AppendResultMeanAndError(std::string & output,const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & mean_and_error,const std::string & units,bool important)159 void AppendResultMeanAndError(std::string &output,
160                               const std::string &measurement,
161                               const std::string &modifier,
162                               const std::string &trace,
163                               const std::string &mean_and_error,
164                               const std::string &units,
165                               bool important)
166 {
167     output +=
168         ResultsToString(measurement, modifier, trace, mean_and_error, "{", "}", units, important);
169 }
170 
PrintResultList(const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & values,const std::string & units,bool important)171 void PrintResultList(const std::string &measurement,
172                      const std::string &modifier,
173                      const std::string &trace,
174                      const std::string &values,
175                      const std::string &units,
176                      bool important)
177 {
178     PrintResultsImpl(measurement, modifier, trace, values, "[", "]", units, important);
179 }
180 
AppendResultList(std::string & output,const std::string & measurement,const std::string & modifier,const std::string & trace,const std::string & values,const std::string & units,bool important)181 void AppendResultList(std::string &output,
182                       const std::string &measurement,
183                       const std::string &modifier,
184                       const std::string &trace,
185                       const std::string &values,
186                       const std::string &units,
187                       bool important)
188 {
189     output += ResultsToString(measurement, modifier, trace, values, "[", "]", units, important);
190 }
191 
PrintSystemCommitCharge(const std::string & test_name,size_t charge,bool important)192 void PrintSystemCommitCharge(const std::string &test_name, size_t charge, bool important)
193 {
194     PrintSystemCommitCharge(stdout, test_name, charge, important);
195 }
196 
PrintSystemCommitCharge(FILE * target,const std::string & test_name,size_t charge,bool important)197 void PrintSystemCommitCharge(FILE *target,
198                              const std::string &test_name,
199                              size_t charge,
200                              bool important)
201 {
202     fprintf(target, "%s", SystemCommitChargeToString(test_name, charge, important).c_str());
203 }
204 
SystemCommitChargeToString(const std::string & test_name,size_t charge,bool important)205 std::string SystemCommitChargeToString(const std::string &test_name, size_t charge, bool important)
206 {
207     std::string trace_name(test_name);
208     std::string output;
209     AppendResult(output, "commit_charge", std::string(), "cc" + trace_name, charge, "kb",
210                  important);
211     return output;
212 }
213 
214 }  // namespace perf_test
215