blob: 47e337bdcafb91eaae577d2b980837f3434805d7 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <lib/fxl/command_line.h>
#include <lib/fxl/files/file.h>
#include <lib/fxl/files/path.h>
#include <lib/fxl/log_settings.h>
#include <lib/fxl/log_settings_command_line.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_printf.h>
#include <lib/fxl/time/stopwatch.h>
#include "garnet/bin/cpuperf/session_result_spec.h"
#include "printer_config.h"
static constexpr char kUsageString[] =
"cpuperf_print [options]\n"
"\n"
"These options are required:\n"
"--session=FILE Session result spec file\n"
" Trace files are assumed to live in the same directory\n"
"\n"
"The remaining options are optional.\n"
"\n"
"General output options:\n"
"--output-format=raw\n"
" Default is \"raw\"\n"
"--output-file=PATH\n"
" For raw the default is stdout.\n"
"\n"
"Logging options:\n"
" --quiet[=LEVEL] Set quietness level (opposite of verbose)\n"
" --verbose[=LEVEL] Set debug verbosity level\n"
" --log-file=FILE Write log output to FILE.\n"
"Quiet supersedes verbose if both are specified.\n"
"Defined log levels:\n"
"-n - verbosity level n\n"
" 0 - INFO - this is the default level\n"
" 1 - WARNING\n"
" 2 - ERROR\n"
" 3 - FATAL\n";
static void PrintUsage(FILE* f) {
fputs(kUsageString, f);
}
static bool ParseArgv(const fxl::CommandLine& cl,
std::string* session_result_spec_path,
cpuperf::SessionResultSpec* out_session_result_spec,
cpuperf::PrinterConfig* out_printer_config) {
std::string arg;
if (!cl.GetOptionValue("session", session_result_spec_path)) {
FXL_LOG(ERROR) << "Missing --session argument";
return false;
}
std::string content;
if (!files::ReadFileToString(*session_result_spec_path, &content)) {
FXL_LOG(ERROR) << "Can't read " << *session_result_spec_path;
return false;
}
if (!DecodeSessionResultSpec(content, out_session_result_spec)) {
return false;
}
if (cl.GetOptionValue("output-format", &arg)) {
if (arg == "raw") {
out_printer_config->output_format = cpuperf::OutputFormat::kRaw;
} else {
FXL_LOG(ERROR) << "Bad value for --output-format: " << arg;
return false;
}
}
if (cl.GetOptionValue("output-file", &arg)) {
out_printer_config->output_file_name = arg;
}
const std::vector<std::string>& positional_args = cl.positional_args();
if (positional_args.size() > 0) {
FXL_LOG(ERROR) << "No positional parameters";
return false;
}
return true;
}
int main(int argc, char** argv) {
fxl::CommandLine cl = fxl::CommandLineFromArgcArgv(argc, argv);
if (!fxl::SetLogSettingsFromCommandLine(cl))
return EXIT_FAILURE;
if (cl.HasOption("help")) {
PrintUsage(stdout);
return EXIT_SUCCESS;
}
std::string session_result_spec_path;
cpuperf::SessionResultSpec session_result_spec;
cpuperf::PrinterConfig printer_config;
if (!ParseArgv(cl, &session_result_spec_path, &session_result_spec,
&printer_config)) {
return EXIT_FAILURE;
}
// Modify the recorded output path prefix to point to where we found the
// session result spec. The directory currently recorded is probably for
// the target.
std::string spec_directory =
files::GetDirectoryName(session_result_spec_path);
if (spec_directory == "") {
spec_directory = ".";
}
std::string path_prefix_basename =
files::GetBaseName(session_result_spec.output_path_prefix);
session_result_spec.output_path_prefix =
spec_directory + "/" + path_prefix_basename;
fxl::Stopwatch stop_watch;
stop_watch.Start();
if (!session_result_spec.config_name.empty()) {
FXL_LOG(INFO) << "Config: " << session_result_spec.config_name;
} else {
FXL_LOG(INFO) << "Config: unnamed";
}
FXL_LOG(INFO) << session_result_spec.num_iterations << " iteration(s), "
<< session_result_spec.num_traces << " trace(s)";
FXL_LOG(INFO) << "Output path prefix: "
<< session_result_spec.output_path_prefix;
uint64_t total_records;
if (printer_config.output_format == cpuperf::OutputFormat::kRaw) {
std::unique_ptr<cpuperf::RawPrinter> printer;
if (!cpuperf::RawPrinter::Create(&session_result_spec,
printer_config.ToRawPrinterConfig(),
&printer)) {
return EXIT_FAILURE;
}
total_records = printer->PrintFiles();
} else {
FXL_LOG(ERROR) << "Invalid output format\n";
return EXIT_FAILURE;
}
fxl::TimeDelta delta = stop_watch.Elapsed();
int64_t seconds = delta.ToSeconds();
int milliseconds = delta.ToMilliseconds() % 1000;
FXL_LOG(INFO) << fxl::StringPrintf(
"%" PRIu64 " records processed in %" PRId64 ".%03d seconds\n",
total_records, seconds, milliseconds);
return EXIT_SUCCESS;
}