1 // Copyright 2015 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "perf_stat_parser.h" 6 7 #include <stdlib.h> // for strtoull and strtod 8 9 #include <vector> 10 11 #include "base/logging.h" 12 13 #include "compat/proto.h" 14 #include "file_utils.h" 15 #include "string_utils.h" 16 17 namespace quipper { 18 19 bool ParsePerfStatFileToProto(const string& path, PerfStatProto* proto) { 20 std::vector<char> data; 21 if (!FileToBuffer(path, &data)) { 22 return false; 23 } 24 string data_str(data.begin(), data.end()); 25 return ParsePerfStatOutputToProto(data_str, proto); 26 } 27 28 bool ParsePerfStatOutputToProto(const string& data, PerfStatProto* proto) { 29 std::vector<string> lines; 30 SplitString(data, '\n', &lines); 31 uint64_t time_ms = 0; 32 for (size_t i = 0; i < lines.size(); ++i) { 33 TrimWhitespace(&lines[i]); 34 // Look for lines of the form: 35 // "name: 123 123 123" 36 // OR 37 // "1.234 seconds time elapsed" 38 std::vector<string> tokens; 39 SplitString(lines[i], ' ', &tokens); 40 if (tokens.size() != 4) { 41 continue; 42 } 43 const string& first_token = tokens[0]; 44 // Look for "name: 123 123 123" 45 if (first_token.back() == ':') { 46 char* endptr; 47 uint64_t count = strtoull(tokens[1].c_str(), &endptr, 10); 48 if (*endptr != '\0') { 49 continue; 50 } 51 auto newline = proto->add_line(); 52 newline->set_count(count); 53 newline->set_event_name(first_token.substr(0, first_token.size() - 1)); 54 } 55 // Look for "1.234 seconds time elapsed" 56 if (tokens[1] == "seconds" && 57 !SecondsStringToMillisecondsUint64(first_token, &time_ms)) { 58 time_ms = 0; 59 } 60 } 61 if (time_ms != 0) { 62 for (int i = 0; i < proto->line_size(); ++i) { 63 proto->mutable_line(i)->set_time_ms(time_ms); 64 } 65 } 66 return proto->line_size() > 0; 67 } 68 69 bool SecondsStringToMillisecondsUint64(const string& str, uint64_t* out) { 70 char* endptr; 71 double seconds = strtod(str.c_str(), &endptr); 72 if (*endptr != '\0') { 73 return false; 74 } 75 if (seconds < 0) { 76 return false; 77 } 78 *out = (static_cast<uint64_t>(seconds * 1000.0 + 0.5)); 79 return true; 80 } 81 82 } // namespace quipper 83