blob: a3142b0e1567ef7e5ae040e95ff6215824a98493 [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
Alex Vakulenko262be3f2014-07-30 15:25:50 -07005#include "debugd/src/perf_tool.h"
Ahmad Sharifae1714d2013-01-17 11:29:37 -08006
Ben Chan9953a592014-02-05 23:32:00 -08007#include <base/strings/string_split.h>
Simon Que21bb7902014-07-28 16:17:20 -07008#include <base/strings/string_util.h>
9
10#include <algorithm>
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070011
Alex Vakulenko262be3f2014-07-30 15:25:50 -070012#include "debugd/src/cpu_info_parser.h"
13#include "debugd/src/process_with_output.h"
Ahmad Sharifae1714d2013-01-17 11:29:37 -080014
Ben Chan55903dd2014-04-24 00:29:04 -070015using base::StringPrintf;
16
Ahmad Shariff5597f62013-04-25 12:25:41 -070017namespace {
18
19// Location of quipper on ChromeOS.
20const char kQuipperLocation[] = "/usr/bin/quipper";
21
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070022// This is the key in /proc/cpuinfo whose value is the model name of the CPU.
23const char kCPUModelNameKey[] = "model name";
Ahmad Shariff5597f62013-04-25 12:25:41 -070024
Simon Que21bb7902014-07-28 16:17:20 -070025// This is registered trademark symbol that appears in model name strings.
26const char kRegisteredTrademarkSymbol[] = "(R)";
27
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070028// Processor model name substrings for which we have perf commands.
29const char* kCPUOddsFiles[] = {
30 "unknown",
31 "core",
Simon Que21bb7902014-07-28 16:17:20 -070032 "celeron-2955u",
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070033 "arm",
34};
Ahmad Shariff5597f62013-04-25 12:25:41 -070035
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070036// Prefix path to attach to the CPU odds file.
Ahmad Sharifbdb33912013-07-16 11:44:49 -040037const char kCPUOddsFilePrefix[] = "/etc/perf_commands/";
Ahmad Shariff5597f62013-04-25 12:25:41 -070038
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070039// Suffix to attach to the CPU odds file.
40const char kCPUOddsFileSuffix[] = ".txt";
Ahmad Shariff5597f62013-04-25 12:25:41 -070041
Simon Que21bb7902014-07-28 16:17:20 -070042// Converts an CPU model name string into a format that can be used as a file
43// name. The rules are:
44// - Replace spaces with hyphens.
45// - Strip all "(R)" symbols.
46// - Convert to lower case.
47std::string ModelNameToFileName(const std::string& model_name) {
48 std::string result = model_name;
49 std::replace(result.begin(), result.end(), ' ', '-');
50 ReplaceSubstringsAfterOffset(&result, 0, kRegisteredTrademarkSymbol, "");
Ben Chane1ca84e2014-09-05 08:20:59 -070051 return base::StringToLowerASCII(result);
Simon Que21bb7902014-07-28 16:17:20 -070052}
53
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070054// Goes through the list of kCPUOddsFiles, and if the any of those strings is a
55// substring of the |cpu_model_name|, returns that string. If no matches are
56// found, returns the first string of |kCPUOddsFiles| ("unknown").
57void GetOddsFilenameForCPU(const std::string& cpu_model_name,
58 std::string* odds_filename) {
Simon Que21bb7902014-07-28 16:17:20 -070059 std::string adjusted_model_name = ModelNameToFileName(cpu_model_name);
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070060 for (size_t i = 0; i < arraysize(kCPUOddsFiles); ++i) {
Simon Que21bb7902014-07-28 16:17:20 -070061 if (adjusted_model_name.find(kCPUOddsFiles[i]) != std::string::npos) {
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070062 *odds_filename = kCPUOddsFiles[i];
63 return;
64 }
65 }
66 *odds_filename = kCPUOddsFiles[0];
Ahmad Shariff5597f62013-04-25 12:25:41 -070067}
68
69} // namespace
70
Ahmad Sharifae1714d2013-01-17 11:29:37 -080071namespace debugd {
72
Ahmad Shariff5597f62013-04-25 12:25:41 -070073PerfTool::PerfTool() {
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070074 std::string cpu_model_name;
75 debugd::CPUInfoParser cpu_info_parser;
76 cpu_info_parser.GetKey(kCPUModelNameKey, &cpu_model_name);
77 std::string odds_filename;
78 GetOddsFilenameForCPU(cpu_model_name, &odds_filename);
Ben Chana0011d82014-05-13 00:19:29 -070079 std::string odds_file_path =
80 std::string(kCPUOddsFilePrefix) + odds_filename + kCPUOddsFileSuffix;
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070081 random_selector_.SetOddsFromFile(odds_file_path);
Ahmad Shariff5597f62013-04-25 12:25:41 -070082}
Ahmad Sharifae1714d2013-01-17 11:29:37 -080083
Ben Chan49d264c2014-08-06 17:38:16 -070084std::vector<uint8_t> PerfTool::GetRichPerfData(const uint32_t& duration_secs,
85 DBus::Error* error) {
David Sharp4fd46762015-02-09 17:31:10 -080086 std::string perf_command_line = random_selector_.GetNext();
Ahmad Shariff5597f62013-04-25 12:25:41 -070087 std::string output_string;
88 GetPerfDataHelper(duration_secs, perf_command_line, error, &output_string);
Ben Chan49d264c2014-08-06 17:38:16 -070089 return std::vector<uint8_t>(output_string.begin(), output_string.end());
Ahmad Shariff5597f62013-04-25 12:25:41 -070090}
91
92void PerfTool::GetPerfDataHelper(const uint32_t& duration_secs,
93 const std::string& perf_command_line,
Ben Chana0011d82014-05-13 00:19:29 -070094 DBus::Error* error,
95 std::string* data_string) {
Ahmad Sharifae1714d2013-01-17 11:29:37 -080096 // This whole method is synchronous, so we create a subprocess, let it run to
97 // completion, then gather up its output to return it.
98 ProcessWithOutput process;
99 process.SandboxAs("root", "root");
100 if (!process.Init())
101 *data_string = "<process init failed>";
102 // If you're going to add switches to a command, have a look at the Process
103 // interface; there's support for adding options specifically.
Ahmad Shariff5597f62013-04-25 12:25:41 -0700104 process.AddArg(kQuipperLocation);
105 process.AddArg(StringPrintf("%u", duration_secs));
106 process.AddArg(perf_command_line);
Ahmad Sharifae1714d2013-01-17 11:29:37 -0800107 // Run the process to completion. If the process might take a while, you may
108 // have to make this asynchronous using .Start().
109 int status = process.Run();
110 if (status != 0)
111 *data_string = StringPrintf("<process exited with status: %d", status);
112 process.GetOutput(data_string);
113}
114
Ben Chana0011d82014-05-13 00:19:29 -0700115} // namespace debugd