summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-08-03 19:40:58 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-08-03 19:40:58 +0000
commitd4e3b2199be1e909698ce4911daf26035ca1bcda (patch)
tree1e5819c3fc3185b58c8dc0c8aedf6e60c54755ef
parent3dafe0b6356473819ea2b6fca022fc9459eb94cd (diff)
parentecc46ef5593604f2ad090e34120c32f7dc22e361 (diff)
downloadextras-d4e3b2199be1e909698ce4911daf26035ca1bcda.tar.gz
Merge "Perfprofd: Add option dump"
-rw-r--r--perfprofd/binder_interface/perfprofd_binder.cc10
-rw-r--r--perfprofd/configreader.cc103
-rw-r--r--perfprofd/configreader.h1
-rw-r--r--perfprofd/perfprofd_threaded_handler.h6
-rw-r--r--perfprofd/tests/perfprofd_test.cc53
5 files changed, 172 insertions, 1 deletions
diff --git a/perfprofd/binder_interface/perfprofd_binder.cc b/perfprofd/binder_interface/perfprofd_binder.cc
index ef7de6dd..a1c77e24 100644
--- a/perfprofd/binder_interface/perfprofd_binder.cc
+++ b/perfprofd/binder_interface/perfprofd_binder.cc
@@ -108,7 +108,15 @@ status_t PerfProfdNativeService::start() {
status_t PerfProfdNativeService::dump(int fd, const Vector<String16> &args) {
auto out = std::fstream(base::StringPrintf("/proc/self/fd/%d", fd));
- out << "Nothing to log, yet!" << std::endl;
+ auto print_config = [&out](bool is_profiling, const Config* config) {
+ if (is_profiling) {
+ out << "Profiling with config: " << ConfigReader::ConfigToString(*config);
+ } else {
+ out << "Not actively profiling.";
+ }
+ };
+ RunOnConfig(print_config);
+ out << std::endl;
return NO_ERROR;
}
diff --git a/perfprofd/configreader.cc b/perfprofd/configreader.cc
index c5442777..44111943 100644
--- a/perfprofd/configreader.cc
+++ b/perfprofd/configreader.cc
@@ -463,6 +463,109 @@ void ConfigReader::FillConfig(Config* config) {
}
}
+namespace {
+
+template <typename T>
+struct OssFormatter {
+};
+
+template <>
+struct OssFormatter<std::string> {
+ void Add(std::ostream& os, const std::string& val) {
+ os << val;
+ }
+};
+
+template <>
+struct OssFormatter<uint32_t> {
+ void Add(std::ostream& os, const uint32_t& val) {
+ os << val;
+ }
+};
+
+template <>
+struct OssFormatter<int32_t> {
+ void Add(std::ostream& os, const int32_t& val) {
+ os << val;
+ }
+};
+
+template <>
+struct OssFormatter<bool> {
+ void Add(std::ostream& os, const bool& val) {
+ os << (val ? 1 : 0);
+ }
+};
+
+
+} // namespace
+
+std::string ConfigReader::ConfigToString(const Config& config) {
+ std::ostringstream oss;
+
+ auto add = [&oss](const char* str, auto val) {
+ if (oss.tellp() != 0) {
+ oss << ' ';
+ }
+ oss << str << '=';
+ OssFormatter<decltype(val)> fmt;
+ fmt.Add(oss, val);
+ };
+
+ add("collection_interval", config.collection_interval_in_s);
+ add("use_fixed_seed", config.use_fixed_seed);
+ add("main_loop_iterations", config.main_loop_iterations);
+
+ add("destination_directory", config.destination_directory); // TODO: Escape.
+ add("config_directory", config.config_directory); // TODO: Escape.
+ add("perf_path", config.perf_path); // TODO: Escape.
+
+ add("sampling_period", config.sampling_period);
+ add("sampling_frequency", config.sampling_frequency);
+
+ add("sample_duration", config.sample_duration_in_s);
+
+ add("only_debug_build", config.only_debug_build);
+
+ add("hardwire_cpus", config.hardwire_cpus);
+
+ add("hardwire_cpus_max_duration", config.hardwire_cpus_max_duration_in_s);
+
+ add("max_unprocessed_profiles", config.max_unprocessed_profiles);
+
+ add("stack_profile", config.stack_profile);
+
+ add("trace_config_read", config.trace_config_read);
+
+ add("collect_cpu_utilization", config.collect_cpu_utilization);
+ add("collect_charging_state", config.collect_charging_state);
+ add("collect_booting", config.collect_booting);
+ add("collect_camera_active", config.collect_camera_active);
+
+ add("process", config.process);
+ add("use_elf_symbolizer", config.use_elf_symbolizer);
+ add("symbolize_everything", config.symbolize_everything);
+ add("compress", config.compress);
+ add("dropbox", config.send_to_dropbox);
+ add("fail_on_unsupported_events", config.fail_on_unsupported_events);
+
+ for (const auto& elem : config.event_config) {
+ std::ostringstream oss_elem;
+ oss_elem << '-' << (elem.group ? 'g' : 'e') << '_';
+ bool first = true;
+ for (const auto& event : elem.events) {
+ if (!first) {
+ oss_elem << ',';
+ }
+ oss_elem << event;
+ first = false;
+ }
+ add(oss_elem.str().c_str(), elem.sampling_period);
+ }
+
+ return oss.str();
+}
+
void ConfigReader::ProtoToConfig(const android::perfprofd::ProfilingConfig& in, Config* out) {
// Copy base proto values.
#define CHECK_AND_COPY_FROM_PROTO(name) \
diff --git a/perfprofd/configreader.h b/perfprofd/configreader.h
index 180e537e..3d2243c5 100644
--- a/perfprofd/configreader.h
+++ b/perfprofd/configreader.h
@@ -60,6 +60,7 @@ class ConfigReader {
void overrideUnsignedEntry(const char *key, unsigned new_value);
void FillConfig(Config* config);
+ static std::string ConfigToString(const Config& config);
static void ProtoToConfig(const android::perfprofd::ProfilingConfig& in, Config* out);
diff --git a/perfprofd/perfprofd_threaded_handler.h b/perfprofd/perfprofd_threaded_handler.h
index 037e24cc..76cdd67a 100644
--- a/perfprofd/perfprofd_threaded_handler.h
+++ b/perfprofd/perfprofd_threaded_handler.h
@@ -170,6 +170,12 @@ class ThreadedHandler {
return true;
}
+ template <typename Fn>
+ void RunOnConfig(Fn& fn) {
+ std::lock_guard<std::mutex> guard(lock_);
+ fn(cur_config_->is_profiling, cur_config_.get());
+ }
+
private:
// Helper for the handler.
HandlerFn GetResultHandler() {
diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc
index 09392054..a26694c7 100644
--- a/perfprofd/tests/perfprofd_test.cc
+++ b/perfprofd/tests/perfprofd_test.cc
@@ -712,6 +712,59 @@ TEST_F(PerfProfdTest, ConfigFileParsing_Events) {
}
}
+
+TEST_F(PerfProfdTest, ConfigDump) {
+ constexpr const char* kConfigElems[] = {
+ "collection_interval=14400",
+ "use_fixed_seed=1",
+ "main_loop_iterations=2",
+ "destination_directory=/does/not/exist",
+ "config_directory=a",
+ "perf_path=/system/xbin/simpleperf2",
+ "sampling_period=3",
+ "sampling_frequency=4",
+ "sample_duration=5",
+ "only_debug_build=1",
+ "hardwire_cpus=1",
+ "hardwire_cpus_max_duration=6",
+ "max_unprocessed_profiles=7",
+ "stack_profile=1",
+ "trace_config_read=1",
+ "collect_cpu_utilization=1",
+ "collect_charging_state=1",
+ "collect_booting=1",
+ "collect_camera_active=1",
+ "process=8",
+ "use_elf_symbolizer=1",
+ "symbolize_everything=1",
+ "compress=1",
+ "dropbox=1",
+ "fail_on_unsupported_events=1",
+ "-e_hello,world=1",
+ "-g_foo,bar=2",
+ "-e_abc,xyz=3",
+ "-g_ftrace:test,ftrace:test2=4",
+ };
+
+ std::string input;
+ for (const char* elem : kConfigElems) {
+ input.append(elem);
+ input.append("\n");
+ }
+
+ ConfigReader reader;
+ std::string error_msg;
+ ASSERT_TRUE(reader.Read(input, false, &error_msg)) << error_msg;
+
+ PerfProfdRunner::LoggingConfig config;
+ reader.FillConfig(&config);
+
+ std::string output = ConfigReader::ConfigToString(config);
+ for (const char* elem : kConfigElems) {
+ EXPECT_TRUE(output.find(elem) != std::string::npos) << elem << " not in " << output;
+ }
+}
+
TEST_F(PerfProfdTest, ProfileCollectionAnnotations)
{
unsigned util1 = collect_cpu_utilization();