blob: fc5fa8159f02b9f87587f98fcfd389f620157a32 [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 "garnet/bin/cpuperf/session_result_spec.h"
#include <lib/syslog/cpp/macros.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/schema.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/json_parser/rapidjson_validation.h"
namespace cpuperf {
namespace {
// Top-level schema.
const char kRootSchema[] = R"({
"type": "object",
"additionalProperties": false,
"properties": {
"config_name": {
"type": "string"
},
"model_name": {
"type": "string"
},
"num_iterations": {
"type": "integer",
"minimum": 1
},
"num_traces": {
"type": "integer",
"minimum": 1
},
"output_path_prefix": {
"type": "string"
}
}
})";
const char kConfigNameKey[] = "config_name";
const char kModelNameKey[] = "model_name";
const char kNumIterationsKey[] = "num_iterations";
const char kNumTracesKey[] = "num_traces";
const char kOutputPathPrefixKey[] = "output_path_prefix";
} // namespace
SessionResultSpec::SessionResultSpec(const std::string& config_name, const std::string& model_name,
size_t num_iterations, size_t num_traces,
const std::string& output_path_prefix)
: config_name(config_name),
model_name(model_name),
num_iterations(num_iterations),
num_traces(num_traces),
output_path_prefix(output_path_prefix) {}
// Given an iteration number and trace number, return the output file.
std::string SessionResultSpec::GetTraceFilePath(size_t iter_num, size_t trace_num) const {
return fxl::StringPrintf("%s.%zu.%zu.cpuperf", output_path_prefix.c_str(), iter_num, trace_num);
}
bool DecodeSessionResultSpec(const std::string& json, SessionResultSpec* out_spec) {
// Initialize schemas for JSON validation.
auto root_schema_result = json_parser::InitSchema(kRootSchema);
if (root_schema_result.is_error()) {
FX_LOGS(ERROR) << "Invalid schema: " << root_schema_result.error_value().ToString();
return false;
}
SessionResultSpec result;
rapidjson::Document document;
document.Parse<rapidjson::kParseCommentsFlag>(json.c_str(), json.size());
if (document.HasParseError()) {
auto offset = document.GetErrorOffset();
auto code = document.GetParseError();
FX_LOGS(ERROR) << "Couldn't parse the session result spec file: offset " << offset << ", "
<< GetParseError_En(code);
return false;
}
auto root_schema = std::move(root_schema_result.value());
auto validation_result =
json_parser::ValidateSchema(document, root_schema, "session result spec");
if (validation_result.is_error()) {
FX_LOGS(ERROR) << "json validation failed: " << validation_result.error_value();
return false;
}
if (document.HasMember(kConfigNameKey)) {
result.config_name = document[kConfigNameKey].GetString();
}
if (document.HasMember(kModelNameKey)) {
result.model_name = document[kModelNameKey].GetString();
}
if (document.HasMember(kNumIterationsKey)) {
result.num_iterations = document[kNumIterationsKey].GetUint();
}
if (document.HasMember(kNumTracesKey)) {
result.num_traces = document[kNumTracesKey].GetUint();
}
if (document.HasMember(kOutputPathPrefixKey)) {
result.output_path_prefix = document[kOutputPathPrefixKey].GetString();
}
*out_spec = std::move(result);
return true;
}
bool WriteSessionResultSpec(const std::string& output_file_path, const SessionResultSpec& spec) {
rapidjson::StringBuffer string_buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(string_buffer);
writer.StartObject();
if (!spec.config_name.empty()) {
writer.Key(kConfigNameKey);
writer.String(spec.config_name.c_str());
}
if (!spec.model_name.empty()) {
writer.Key(kModelNameKey);
writer.String(spec.model_name.c_str());
}
writer.Key(kNumIterationsKey);
writer.Uint(spec.num_iterations);
writer.Key(kNumTracesKey);
writer.Uint(spec.num_traces);
writer.Key(kOutputPathPrefixKey);
writer.String(spec.output_path_prefix.c_str());
writer.EndObject();
std::string encoded = string_buffer.GetString();
if (!files::WriteFile(output_file_path, encoded.data(), encoded.size())) {
FX_LOGS(ERROR) << "Error writing to: " << output_file_path;
return false;
}
return true;
}
} // namespace cpuperf