HEBench
report_gen/report_compiler/src/main.cpp
Go to the documentation of this file.
1 
2 // Copyright (C) 2021 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <filesystem>
6 #include <iostream>
7 #include <sstream>
8 #include <stdexcept>
9 #include <string>
10 #include <vector>
11 
12 #include "hebench/modules/args_parser/include/args_parser.h"
13 
15 
16 using namespace std::literals;
17 
18 struct ProgramConfig
19 {
20  std::filesystem::path input_file;
22  bool b_silent;
23  char time_unit;
27 
28  static constexpr const char *TimeUnit = "--time_unit";
29  static constexpr const char *TimeUnitStats = "--time_unit_stats";
30  static constexpr const char *TimeUnitOverview = "--time_unit_overview";
31  static constexpr const char *TimeUnitSummary = "--time_unit_summary";
32  static constexpr const char *ShowOverview = "--show_overview";
33  static constexpr const char *SilentRun = "--silent_run";
34 
35  static constexpr bool DefaultShowOverView = true;
36 
37  void initializeConfig(const hebench::ArgsParser &parser);
38  void showConfig(std::ostream &os) const;
39  static void showVersion(std::ostream &os);
40  static std::string getTimeUnitName(char time_unit, const std::string &default_name = "(default)");
41 
42 private:
43  static const std::unordered_set<std::string> m_allowed_time_units;
44 };
45 
46 const std::unordered_set<std::string> ProgramConfig::m_allowed_time_units({ "s", "ms", "us", "ns" });
47 
48 std::string ProgramConfig::getTimeUnitName(char time_unit, const std::string &default_name)
49 {
50  std::string retval;
51  switch (time_unit)
52  {
53  case 'm':
54  retval = "milliseconds";
55  break;
56  case 'u':
57  retval = "microseconds";
58  break;
59  case 'n':
60  retval = "nanoseconds";
61  break;
62  default:
63  retval = default_name;
64  break;
65  } // end switch
66  return retval;
67 }
68 
69 void ProgramConfig::initializeConfig(const hebench::ArgsParser &parser)
70 {
71  input_file = parser.getPositionalValue(0);
72  input_file = std::filesystem::canonical(input_file);
73 
74  parser.getValue<bool>(b_show_overview, ShowOverview, DefaultShowOverView);
75  b_silent = parser.hasArgument(SilentRun);
76 
77  std::string s_tmp;
78 
79  if (parser.hasArgument(TimeUnit))
80  {
81  parser.getValue<std::string>(s_tmp, TimeUnit);
82  if (m_allowed_time_units.count(s_tmp) <= 0)
83  throw hebench::ArgsParser::InvalidArgument("Invalid argument value for parameter \"" + std::string(TimeUnit) + "\": " + s_tmp);
84  }
85  time_unit = s_tmp.empty() ? 0 : s_tmp.front();
86 
87  s_tmp.clear();
88  if (parser.hasArgument(TimeUnitOverview))
89  {
90  parser.getValue<std::string>(s_tmp, TimeUnitOverview);
91  if (m_allowed_time_units.count(s_tmp) <= 0)
92  throw hebench::ArgsParser::InvalidArgument("Invalid argument value for parameter \"" + std::string(TimeUnitOverview) + "\": " + s_tmp);
93  }
94  time_unit_overview = s_tmp.empty() ? 0 : s_tmp.front();
95 
96  s_tmp.clear();
97  if (parser.hasArgument(TimeUnitStats))
98  {
99  parser.getValue<std::string>(s_tmp, TimeUnitStats);
100  if (m_allowed_time_units.count(s_tmp) <= 0)
101  throw hebench::ArgsParser::InvalidArgument("Invalid argument value for parameter \"" + std::string(TimeUnitStats) + "\": " + s_tmp);
102  }
103  time_unit_stats = s_tmp.empty() ? 0 : s_tmp.front();
104 
105  s_tmp.clear();
106  if (parser.hasArgument(TimeUnitSummary))
107  {
108  parser.getValue<std::string>(s_tmp, TimeUnitSummary);
109  if (m_allowed_time_units.count(s_tmp) <= 0)
110  throw hebench::ArgsParser::InvalidArgument("Invalid argument value for parameter \"" + std::string(TimeUnitSummary) + "\": " + s_tmp);
111  }
112  time_unit_summary = s_tmp.empty() ? 0 : s_tmp.front();
113 }
114 
115 void ProgramConfig::showConfig(std::ostream &os) const
116 {
117  std::string fallback_time_unit = getTimeUnitName(time_unit);
118  os << "==================" << std::endl
119  << "Global Configuration:" << std::endl
120  << " Input file: " << input_file << std::endl
121  << " Show overview: " << (b_show_overview ? "Yes" : "No") << std::endl
122  << " Overview time unit: " << (time_unit_overview == 0 ? fallback_time_unit : getTimeUnitName(time_unit_overview)) << std::endl
123  << " Summary time unit: " << (time_unit_summary == 0 ? fallback_time_unit : getTimeUnitName(time_unit_summary)) << std::endl
124  << " Statistics time unit: " << (time_unit_stats == 0 ? fallback_time_unit : getTimeUnitName(time_unit_stats)) << std::endl;
125  os << "==================" << std::endl;
126 }
127 
128 void ProgramConfig::showVersion(std::ostream &os)
129 {
130  (void)os;
131 }
132 
133 void initArgsParser(hebench::ArgsParser &parser, int argc, char **argv)
134 {
135  parser.addPositionalArgument("input_file",
136  " Input file to be used during report generation. This can be a single\n"
137  " benchmark report generated by Test Harness or a file containing a list\n"
138  " of report files to process. The directory for this file must be\n"
139  " available for writing.");
140  parser.addArgument(ProgramConfig::TimeUnit, "-tu", 1, "<time_unit_name>",
141  " [OPTIONAL] Specifies the time unit to be used for the generated reports\n"
142  " if no time unit is specified for a report type. The value of this\n"
143  " parameter must be one of:\n"
144  " \"s\" - seconds\n"
145  " \"ms\" - milliseconds\n"
146  " \"us\" - microseconds\n"
147  " \"ns\" - nanoseconds\n"
148  " If missing, an appropriate unit will be automatically selected per\n"
149  " benchmark.");
150  parser.addArgument(ProgramConfig::TimeUnitOverview, "-tuo", 1, "<time_unit_name>",
151  " [OPTIONAL] Specifies the time unit to be used for the generated overview.\n"
152  " If no time unit is specified, the fallback time unit specified for\n"
153  " parameter `"
154  + std::string(ProgramConfig::TimeUnit) + "` is used instead.");
155  parser.addArgument(ProgramConfig::TimeUnitStats, "-tut", 1, "<time_unit_name>",
156  " [OPTIONAL] Specifies the time unit to be used for the generated\n"
157  " statistics. If no time unit is specified, the fallback time unit\n"
158  " specified for parameter `"
159  + std::string(ProgramConfig::TimeUnit) + "` is used instead.");
160  parser.addArgument(ProgramConfig::TimeUnitSummary, "-tus", 1, "<time_unit_name>",
161  " [OPTIONAL] Specifies the time unit to be used for the generated\n"
162  " summaries. If no time unit is specified, the fallback time unit\n"
163  " specified for parameter `"
164  + std::string(ProgramConfig::TimeUnit) + "` is used instead.");
165  parser.addArgument(ProgramConfig::ShowOverview, "--overview", 1, "<true | false | 1 | 0>",
166  " [OPTIONAL] Specifies whether or not to display report overview to\n"
167  " standard output. If option is missing, default is \"true\".");
168  parser.addArgument(ProgramConfig::SilentRun, "--silent", 0, "",
169  " [OPTIONAL] When present, this flag indicates that the run must be\n"
170  " silent. Only specifically requested outputs will be displayed to\n"
171  " standard output. When running silent, important messages, warnings and\n"
172  " errors will be sent to standard error stream `stderr`.");
173  parser.parse(argc, argv);
174 }
175 
176 int main(int argc, char **argv)
177 {
178  int retval = 0;
179 
180  std::stringstream ss_err;
181  ProgramConfig config;
182  hebench::ArgsParser args_parser;
183 
184  try
185  {
186  initArgsParser(args_parser, argc, argv);
187  config.initializeConfig(args_parser);
188 
189  if (!config.b_silent)
190  {
191  std::cout << "HEBench Report Compiler" << std::endl
192  << std::endl;
193  config.showConfig(std::cout);
194  std::cout << std::endl;
195  } // end if
196 
198  std::string s_input_file = config.input_file.string();
199  std::vector<char> c_error_msg(1024, 0);
200 
201  compile_config.input_file = s_input_file.c_str();
202  compile_config.b_show_overview = config.b_show_overview ? 1 : 0;
203  compile_config.b_silent = config.b_silent ? 1 : 0;
204  compile_config.time_unit = config.time_unit;
205  compile_config.time_unit_stats = config.time_unit_stats;
206  compile_config.time_unit_overview = config.time_unit_overview;
207  compile_config.time_unit_summary = config.time_unit_summary;
208 
209  if (!hebench::ReportGen::Compiler::compile(&compile_config, c_error_msg.data(), c_error_msg.size()))
210  throw std::runtime_error(c_error_msg.data());
211  }
212  catch (hebench::ArgsParser::HelpShown &)
213  {
214  // no error
215  }
216  catch (hebench::ArgsParser::InvalidArgument &ap_ex)
217  {
218  ss_err << "Error occurred with message: " << std::endl
219  << ap_ex.what() << std::endl
220  << std::endl;
221  args_parser.printUsage(ss_err);
222  retval = -1;
223  }
224  catch (std::exception &ex)
225  {
226  ss_err << "ERROR: " << std::endl
227  << ex.what() << std::endl;
228  retval = -1;
229  }
230  catch (...)
231  {
232  ss_err << "Unexpected error occurred!" << std::endl;
233  retval = -1;
234  }
235 
236  if (retval)
237  {
238  std::cerr << std::endl
239  << ss_err.str() << std::endl
240  << "Terminated with errors." << std::endl;
241  } // end if
242  else if (!config.b_silent)
243  std::cout << std::endl
244  << "Complete!" << std::endl;
245 
246  return retval;
247 }
char time_unit_overview
Time unit for report overview. If 0, the fallback time_unit will be used.
int32_t b_silent
If non-zero, the run details will be omited. Any warning, error, or important messages are directed t...
const char * input_file
C-string containing the input file name.
char time_unit_stats
Time unit for report statistics. If 0, the fallback time_unit will be used.
int32_t compile(const ReportCompilerConfigC *p_config, char *s_error, size_t s_error_size)
Runs the compiler using the specified configuration.
char time_unit_summary
Time unit for report summaries. If 0, the fallback time_unit will be used.
int32_t b_show_overview
If non-zero, the compiled overview will be output to stdout.
char time_unit
Fallback time unit when no time unit is specified for a specific output.
int main(int argc, char **argv)
void initArgsParser(hebench::ArgsParser &parser, int argc, char **argv)
static constexpr const char * ShowOverview
void initializeConfig(const hebench::ArgsParser &parser)
static std::ostream & showVersion(std::ostream &os)
static constexpr const char * TimeUnit
static constexpr const char * TimeUnitSummary
static void showVersion(std::ostream &os)
static constexpr const char * TimeUnitOverview
void showConfig(std::ostream &os) const
static std::string getTimeUnitName(char time_unit, const std::string &default_name="(default)")
static constexpr const char * SilentRun
static constexpr const char * TimeUnitStats