// Copyright 2015 The Chromium OS 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 "perf_stat_parser.h" #include <stdlib.h> // for strtoull and strtod #include <vector> #include "base/logging.h" #include "compat/proto.h" #include "file_utils.h" #include "string_utils.h" namespace quipper { bool ParsePerfStatFileToProto(const string& path, PerfStatProto* proto) { std::vector<char> data; if (!FileToBuffer(path, &data)) { return false; } string data_str(data.begin(), data.end()); return ParsePerfStatOutputToProto(data_str, proto); } bool ParsePerfStatOutputToProto(const string& data, PerfStatProto* proto) { std::vector<string> lines; SplitString(data, '\n', &lines); uint64_t time_ms = 0; for (size_t i = 0; i < lines.size(); ++i) { TrimWhitespace(&lines[i]); // Look for lines of the form: // "name: 123 123 123" // OR // "1.234 seconds time elapsed" std::vector<string> tokens; SplitString(lines[i], ' ', &tokens); if (tokens.size() != 4) { continue; } const string& first_token = tokens[0]; // Look for "name: 123 123 123" if (first_token.back() == ':') { char* endptr; uint64_t count = strtoull(tokens[1].c_str(), &endptr, 10); if (*endptr != '\0') { continue; } auto newline = proto->add_line(); newline->set_count(count); newline->set_event_name(first_token.substr(0, first_token.size() - 1)); } // Look for "1.234 seconds time elapsed" if (tokens[1] == "seconds" && !SecondsStringToMillisecondsUint64(first_token, &time_ms)) { time_ms = 0; } } if (time_ms != 0) { for (int i = 0; i < proto->line_size(); ++i) { proto->mutable_line(i)->set_time_ms(time_ms); } } return proto->line_size() > 0; } bool SecondsStringToMillisecondsUint64(const string& str, uint64_t* out) { char* endptr; double seconds = strtod(str.c_str(), &endptr); if (*endptr != '\0') { return false; } if (seconds < 0) { return false; } *out = (static_cast<uint64_t>(seconds * 1000.0 + 0.5)); return true; } } // namespace quipper