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
ParsePerfStatFileToProto(const string & path,PerfStatProto * proto)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
ParsePerfStatOutputToProto(const string & data,PerfStatProto * proto)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
SecondsStringToMillisecondsUint64(const string & str,uint64_t * out)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