Home | History | Annotate | Download | only in quipper
      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