cpp-stat-bench 0.24.0
Benchmark library with statistics for C++.
Loading...
Searching...
No Matches
create_data_table.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#include "create_data_table.h"
21
22#include <algorithm>
23#include <cstddef>
24#include <functional>
25#include <memory>
26#include <string>
27#include <unordered_map>
28#include <variant>
29#include <vector>
30
31#include <fmt/base.h>
32#include <fmt/format.h>
33#include <plotly_plotter/json_converter_decl.h>
34#include <plotly_plotter/json_value.h>
35
36#include "common_labels.h"
46
47namespace plotly_plotter {
48
53template <>
54class json_converter<stat_bench::param::ParameterValueVariant> {
55public:
62 static void to_json(
63 const stat_bench::param::ParameterValueVariant& from, json_value& to) {
64 std::visit([&to](const auto& value) { to = value; }, from);
65 }
66};
67
68} // namespace plotly_plotter
69
70namespace fmt {
71
76template <>
77struct formatter<stat_bench::param::ParameterValueVariant>
78 : public formatter<string_view> {
86 auto format(const stat_bench::param::ParameterValueVariant& val,
87 format_context& context) const -> format_context::iterator {
88 return std::visit(
89 [&context](const auto& value) {
90 return fmt::format_to(context.out(), "{}", value);
91 },
92 val);
93 }
94};
95
96} // namespace fmt
97
98namespace stat_bench {
99namespace plots {
100
102 const std::vector<measurer::Measurement>& measurements,
103 const std::vector<param::ParameterName>& parameter_names)
104 -> plotly_plotter::data_table {
105 std::vector<std::string> case_names;
106 std::vector<double> processing_times;
107 std::vector<double> processing_time_errors;
108 std::unordered_map<param::ParameterName,
109 std::vector<param::ParameterValueVariant>>
110 parameter_values_map;
111
112 for (const auto& measurement : measurements) {
113 const auto& case_name = measurement.case_info().case_name();
114 auto params_without_target = measurement.cond().params();
115 for (const auto& parameter_name : parameter_names) {
116 params_without_target =
117 params_without_target.clone_without(parameter_name);
118 }
119 const auto case_name_for_plot =
120 generate_plot_name(case_name, params_without_target);
121 case_names.push_back(case_name_for_plot.str());
122
123 processing_times.push_back(measurement.durations_stat().mean());
124 processing_time_errors.push_back(
125 measurement.durations_stat().standard_error());
126
127 for (const auto& parameter_name : parameter_names) {
128 parameter_values_map[parameter_name].push_back(
129 measurement.cond().params().get_as_variant(parameter_name));
130 }
131 }
132
133 plotly_plotter::data_table table;
134 table.emplace(case_name_label, std::move(case_names));
135 table.emplace(time_label, std::move(processing_times));
136 table.emplace(time_error_label, std::move(processing_time_errors));
137 for (const auto& parameter_name : parameter_names) {
138 table.emplace(parameter_name.str().str(),
139 std::move(parameter_values_map[parameter_name]));
140 }
141 return table;
142}
143
144namespace {
145
146auto create_data_table_with_custom_output_without_stat(
147 const std::vector<measurer::Measurement>& measurements,
148 const std::vector<param::ParameterName>& parameter_names,
149 const CustomOutputName& output_name)
150 -> std::pair<plotly_plotter::data_table, bool> {
151 std::vector<std::string> case_names;
152 std::vector<double> processing_times;
153 std::vector<double> processing_time_errors;
154 std::unordered_map<param::ParameterName,
155 std::vector<param::ParameterValueVariant>>
156 parameter_values_map;
157 std::vector<double> custom_outputs;
158
159 for (const auto& measurement : measurements) {
160 const auto& case_name = measurement.case_info().case_name();
161 auto params_without_target = measurement.cond().params();
162 for (const auto& parameter_name : parameter_names) {
163 params_without_target =
164 params_without_target.clone_without(parameter_name);
165 }
166 const auto case_name_for_plot =
167 generate_plot_name(case_name, params_without_target);
168 case_names.push_back(case_name_for_plot.str());
169
170 processing_times.push_back(measurement.durations_stat().mean());
171 processing_time_errors.push_back(
172 measurement.durations_stat().standard_error());
173
174 for (const auto& parameter_name : parameter_names) {
175 parameter_values_map[parameter_name].push_back(
176 measurement.cond().params().get_as_variant(parameter_name));
177 }
178
179 const auto& current_custom_outputs = measurement.custom_outputs();
180 const auto iter = std::find_if(current_custom_outputs.begin(),
181 current_custom_outputs.end(), [&output_name](const auto& pair) {
182 return pair.first == output_name;
183 });
184 if (iter == current_custom_outputs.end()) {
185 throw StatBenchException(fmt::format(
186 "Custom output {} not found in a measurement.", output_name));
187 }
188 custom_outputs.push_back(iter->second);
189 }
190
191 plotly_plotter::data_table table;
192 table.emplace(case_name_label, std::move(case_names));
193 table.emplace(time_label, std::move(processing_times));
194 table.emplace(time_error_label, std::move(processing_time_errors));
195 for (const auto& parameter_name : parameter_names) {
196 table.emplace(parameter_name.str().str(),
197 std::move(parameter_values_map[parameter_name]));
198 }
199 table.emplace(output_name.str().str(), std::move(custom_outputs));
200
201 constexpr bool has_error = false;
202 return {std::move(table), has_error};
203}
204
205auto create_data_table_with_custom_output_with_stat(
206 const std::vector<measurer::Measurement>& measurements,
207 const std::vector<param::ParameterName>& parameter_names,
208 const CustomOutputName& output_name)
209 -> std::pair<plotly_plotter::data_table, bool> {
210 std::vector<std::string> case_names;
211 std::vector<double> processing_times;
212 std::vector<double> processing_time_errors;
213 std::unordered_map<param::ParameterName,
214 std::vector<param::ParameterValueVariant>>
215 parameter_values_map;
216 std::vector<double> custom_outputs;
217 std::vector<double> custom_output_errors;
218
219 for (const auto& measurement : measurements) {
220 const auto& case_name = measurement.case_info().case_name();
221 auto params_without_target = measurement.cond().params();
222 for (const auto& parameter_name : parameter_names) {
223 params_without_target =
224 params_without_target.clone_without(parameter_name);
225 }
226 const auto case_name_for_plot =
227 generate_plot_name(case_name, params_without_target);
228 case_names.push_back(case_name_for_plot.str());
229
230 processing_times.push_back(measurement.durations_stat().mean());
231 processing_time_errors.push_back(
232 measurement.durations_stat().standard_error());
233
234 for (const auto& parameter_name : parameter_names) {
235 parameter_values_map[parameter_name].push_back(
236 measurement.cond().params().get_as_variant(parameter_name));
237 }
238
239 const auto& current_custom_outputs = measurement.custom_stat_outputs();
240 const auto iter = std::find_if(current_custom_outputs.begin(),
241 current_custom_outputs.end(), [&output_name](const auto& output) {
242 return output->name() == output_name;
243 });
244 if (iter == current_custom_outputs.end()) {
245 throw StatBenchException(fmt::format(
246 "Custom output {} not found in a measurement.", output_name));
247 }
248 const std::size_t index = iter - current_custom_outputs.begin();
249 const auto& stat = measurement.custom_stat().at(index);
250 custom_outputs.push_back(stat.mean());
251 custom_output_errors.push_back(stat.standard_error());
252 }
253
254 plotly_plotter::data_table table;
255 table.emplace(case_name_label, std::move(case_names));
256 table.emplace(time_label, std::move(processing_times));
257 table.emplace(time_error_label, std::move(processing_time_errors));
258 for (const auto& parameter_name : parameter_names) {
259 table.emplace(parameter_name.str().str(),
260 std::move(parameter_values_map[parameter_name]));
261 }
262 table.emplace(output_name.str().str(), std::move(custom_outputs));
263 table.emplace(fmt::format("Error of {}", output_name.str()),
264 std::move(custom_output_errors));
265
266 constexpr bool has_error = true;
267 return {std::move(table), has_error};
268}
269
270} // namespace
271
273 const std::vector<measurer::Measurement>& measurements,
274 const std::vector<param::ParameterName>& parameter_names,
275 const CustomOutputName& output_name)
276 -> std::pair<plotly_plotter::data_table, bool> {
277 const auto& first_custom_outputs = measurements.front().custom_outputs();
278 const auto first_custom_output_iter = std::find_if(
279 first_custom_outputs.begin(), first_custom_outputs.end(),
280 [&output_name](const auto& pair) { return pair.first == output_name; });
281 if (first_custom_output_iter != first_custom_outputs.end()) {
282 // Case of custom output without statistics.
283 return create_data_table_with_custom_output_without_stat(
284 measurements, parameter_names, output_name);
285 }
286 // Case of custom output with statistics.
287 return create_data_table_with_custom_output_with_stat(
288 measurements, parameter_names, output_name);
289}
290
292 const std::vector<measurer::Measurement>& measurements,
293 const std::vector<param::ParameterName>& parameter_names)
294 -> plotly_plotter::data_table {
295 std::vector<std::string> case_names;
296 std::vector<std::size_t> indices;
297 std::vector<double> processing_times;
298 std::unordered_map<param::ParameterName,
299 std::vector<param::ParameterValueVariant>>
300 parameter_values_map;
301
302 for (const auto& measurement : measurements) {
303 const auto& case_name = measurement.case_info().case_name();
304 auto params_without_target = measurement.cond().params();
305 for (const auto& parameter_name : parameter_names) {
306 params_without_target =
307 params_without_target.clone_without(parameter_name);
308 }
309 const auto case_name_for_plot =
310 generate_plot_name(case_name, params_without_target);
311
312 const auto processing_times_for_plot =
313 measurement.durations_stat().unsorted_samples();
314 const std::size_t num_samples = processing_times_for_plot.size();
315
316 case_names.insert(
317 case_names.end(), num_samples, case_name_for_plot.str());
318
319 for (std::size_t i = 0; i < num_samples; ++i) {
320 indices.push_back(i + 1);
321 }
322
323 processing_times.insert(processing_times.end(),
324 processing_times_for_plot.begin(), processing_times_for_plot.end());
325
326 for (const auto& parameter_name : parameter_names) {
327 const auto parameter_value =
328 measurement.cond().params().get_as_variant(parameter_name);
329 parameter_values_map[parameter_name].insert(
330 parameter_values_map[parameter_name].end(), num_samples,
331 parameter_value);
332 }
333 }
334
335 plotly_plotter::data_table table;
336 table.emplace(case_name_label, std::move(case_names));
337 table.emplace(sample_index_label, std::move(indices));
338 table.emplace(time_label, std::move(processing_times));
339 for (const auto& parameter_name : parameter_names) {
340 table.emplace(parameter_name.str().str(),
341 std::move(parameter_values_map[parameter_name]));
342 }
343 return table;
344}
345
347 const std::vector<measurer::Measurement>& measurements)
348 -> plotly_plotter::data_table {
349 std::vector<std::string> case_names;
350 std::vector<double> probabilities;
351 std::vector<double> processing_times;
352
353 for (const auto& measurement : measurements) {
354 const auto& case_name = measurement.case_info().case_name();
355 const auto& params = measurement.cond().params();
356 const auto case_name_for_plot = generate_plot_name(case_name, params);
357
358 const auto processing_times_for_plot =
359 measurement.durations_stat().sorted_samples();
360 const std::size_t num_samples = processing_times_for_plot.size();
361
362 case_names.insert(
363 case_names.end(), num_samples, case_name_for_plot.str());
364 for (std::size_t i = 0; i < num_samples; ++i) {
365 probabilities.push_back(
366 static_cast<double>(i + 1) / static_cast<double>(num_samples));
367 }
368 processing_times.insert(processing_times.end(),
369 processing_times_for_plot.begin(), processing_times_for_plot.end());
370 }
371
372 plotly_plotter::data_table table;
373 table.emplace(case_name_label, std::move(case_names));
374 table.emplace(cumulative_probability_label, std::move(probabilities));
375 table.emplace(time_label, std::move(processing_times));
376 return table;
377}
378
379} // namespace plots
380} // namespace stat_bench
Definition of BenchmarkCondition class.
Definition of BenchmarkFullName class.
Class of names of custom outputs.
Class of names of parameters.
Definition of constants for labels in plots.
Declaration of create_data_table function.
Namespace of fmt library.
std::variant< bool, std::intmax_t, std::uintmax_t, long double, std::string > ParameterValueVariant
Type of variant of parameter values.
Namespace of plotting.
Definition box_plot.h:28
constexpr const char * time_label
Label for processing time in plots.
auto create_data_table_with_mean_time(const std::vector< measurer::Measurement > &measurements, const std::vector< param::ParameterName > &parameter_names) -> plotly_plotter::data_table
Create a data table with the mean of processing time.
auto create_data_table_for_cdf_plot(const std::vector< measurer::Measurement > &measurements) -> plotly_plotter::data_table
Create a data table for cumulative distribution functions.
auto create_data_table_with_custom_output(const std::vector< measurer::Measurement > &measurements, const std::vector< param::ParameterName > &parameter_names, const CustomOutputName &output_name) -> std::pair< plotly_plotter::data_table, bool >
Create a data table with a custom output.
constexpr const char * time_error_label
Label for errors of processing time in plots.
constexpr const char * sample_index_label
Label for sample index in plots.
constexpr const char * cumulative_probability_label
Label for cumulative probability in plots.
auto generate_plot_name(const BenchmarkCaseName &case_name, const param::ParameterDict &params) -> util::Utf8String
Generate a name for a plot.
constexpr const char * case_name_label
Label for case names in plots.
auto create_data_table_with_all_time(const std::vector< measurer::Measurement > &measurements, const std::vector< param::ParameterName > &parameter_names) -> plotly_plotter::data_table
Create a data table with all samples of processing time.
Namespace of stat_bench source codes.
Definition of ParameterDict class.
Definition of ParameterName class.
Definition of ParameterValue class.
Declaration of utility functions for plots.
Definition of StatBenchException class.
Definition of Statistics class.
Definition of Utf8String class.