普通文本  |  83行  |  2.17 KB

// 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