blob: 67ba6dc301019327bfe8e30b87dd6a2661127f54 [file] [log] [blame]
Ahmad Sharifae1714d2013-01-17 11:29:37 -08001// Copyright (c) 2013 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_tool.h"
6
7#include "process_with_output.h"
8
Ahmad Shariff5597f62013-04-25 12:25:41 -07009namespace {
10
11// Location of quipper on ChromeOS.
12const char kQuipperLocation[] = "/usr/bin/quipper";
13
14// Base perf command line to be used.
15const char kPerfRecord[] = "/usr/sbin/perf record -a";
16
17// This flag enables perf to run in callgraph mode.
18const char kCallGraphMode[] = " -g";
19
20// This flag enables perf to run in branch mode.
21const char kBranchMode[] = " -b";
22
23// This flag enables perf to record cycle events.
24const char kCyclesEvent[] = " -e cycles";
25
26// This flag enables perf to record iTLB-miss events.
27const char kITLBMissesEvent[] = " -e iTLB-misses";
28
29// This flag enables perf to record dTLB-miss events.
30const char kDTLBMissesEvent[] = " -e dTLB-misses";
31
32void PopulateOdds(std::map<std::string, float>* odds) {
33 std::string base_perf_command = kPerfRecord;
34 (*odds)[base_perf_command] = 80;
35 (*odds)[base_perf_command + kCallGraphMode] = 5;
36 (*odds)[base_perf_command + kBranchMode] = 5;
37 (*odds)[base_perf_command + kITLBMissesEvent] = 5;
38 (*odds)[base_perf_command + kDTLBMissesEvent] = 5;
39}
40
41} // namespace
42
Ahmad Sharifae1714d2013-01-17 11:29:37 -080043namespace debugd {
44
Ahmad Shariff5597f62013-04-25 12:25:41 -070045PerfTool::PerfTool() {
46 std::map<std::string, float> odds;
47 PopulateOdds(&odds);
48 random_selector_.SetOdds(odds);
49}
Ahmad Sharifae1714d2013-01-17 11:29:37 -080050
51PerfTool::~PerfTool() { }
52
53// Tool methods have the same signature as the generated DBus adaptors. Most
54// pertinently, this means they take their DBus::Error argument as a non-const
55// reference (hence the NOLINT). Tool methods are generally written in
56// can't-fail style, since their output is usually going to be displayed to the
57// user; instead of returning a DBus exception, we tend to return a string
58// indicating what went wrong.
Ahmad Shariff5597f62013-04-25 12:25:41 -070059std::vector<uint8> PerfTool::GetPerfData(const uint32_t& duration_secs,
60 DBus::Error& error) { // NOLINT
Ahmad Sharifae1714d2013-01-17 11:29:37 -080061 std::string output_string;
Ahmad Shariff5597f62013-04-25 12:25:41 -070062 GetPerfDataHelper(duration_secs, kPerfRecord, error, &output_string);
Ahmad Sharifae1714d2013-01-17 11:29:37 -080063 std::vector<uint8> output_vector(output_string.begin(),
64 output_string.end());
65 return output_vector;
66}
67
Ahmad Shariff5597f62013-04-25 12:25:41 -070068std::vector<uint8> PerfTool::GetRichPerfData(const uint32_t& duration_secs,
69 DBus::Error& error) { // NOLINT
70 std::string perf_command_line;
71 random_selector_.GetNext(&perf_command_line);
72 std::string output_string;
73 GetPerfDataHelper(duration_secs, perf_command_line, error, &output_string);
74 return std::vector<uint8>(output_string.begin(), output_string.end());
75}
76
77void PerfTool::GetPerfDataHelper(const uint32_t& duration_secs,
78 const std::string& perf_command_line,
Ahmad Sharifae1714d2013-01-17 11:29:37 -080079 DBus::Error& error,
80 std::string* data_string) { // NOLINT
Ahmad Sharifae1714d2013-01-17 11:29:37 -080081 // This whole method is synchronous, so we create a subprocess, let it run to
82 // completion, then gather up its output to return it.
83 ProcessWithOutput process;
84 process.SandboxAs("root", "root");
85 if (!process.Init())
86 *data_string = "<process init failed>";
87 // If you're going to add switches to a command, have a look at the Process
88 // interface; there's support for adding options specifically.
Ahmad Shariff5597f62013-04-25 12:25:41 -070089 process.AddArg(kQuipperLocation);
90 process.AddArg(StringPrintf("%u", duration_secs));
91 process.AddArg(perf_command_line);
Ahmad Sharifae1714d2013-01-17 11:29:37 -080092 // Run the process to completion. If the process might take a while, you may
93 // have to make this asynchronous using .Start().
94 int status = process.Run();
95 if (status != 0)
96 *data_string = StringPrintf("<process exited with status: %d", status);
97 process.GetOutput(data_string);
98}
99
100}; // namespace debugd
101