diff options
author | Yabin Cui <yabinc@google.com> | 2019-08-20 17:18:49 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-08-20 17:18:49 -0700 |
commit | 5507a26a7c8dd819b201bbb0d516084eb05c9247 (patch) | |
tree | c6bd93aeb365e59354f88f54ca4a44d96285216a | |
parent | b6d4993018c56422871744c579dedca45fdf3ff8 (diff) | |
parent | 5ff5b91fdc0b07bebaaecd76e47d5c57571ca5ad (diff) | |
download | extras-5507a26a7c8dd819b201bbb0d516084eb05c9247.tar.gz |
Merge "simpleperf: add --use-devfreq-counters option."
am: 5ff5b91fdc
Change-Id: I6f741f3981256dafb9713684bda6a3d8ec2f6182
-rw-r--r-- | simpleperf/cmd_stat.cpp | 102 | ||||
-rw-r--r-- | simpleperf/cmd_stat_test.cpp | 8 |
2 files changed, 91 insertions, 19 deletions
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp index bc047cb8..06f45187 100644 --- a/simpleperf/cmd_stat.cpp +++ b/simpleperf/cmd_stat.cpp @@ -94,6 +94,16 @@ struct CounterSummary { return type_name + ":" + modifier; } + bool IsMonitoredAllTheTime() const { + // If an event runs all the time it is enabled (by not sharing hardware + // counters with other events), the scale of its summary is usually within + // [1, 1 + 1e-5]. By setting SCALE_ERROR_LIMIT to 1e-5, We can identify + // events monitored all the time in most cases while keeping the report + // error rate <= 1e-5. + constexpr double SCALE_ERROR_LIMIT = 1e-5; + return (fabs(scale - 1.0) < SCALE_ERROR_LIMIT); + } + private: std::string ReadableCountValue(bool csv) { if (type_name == "cpu-clock" || type_name == "task-clock") { @@ -117,16 +127,6 @@ struct CounterSummary { } } } - - bool IsMonitoredAllTheTime() const { - // If an event runs all the time it is enabled (by not sharing hardware - // counters with other events), the scale of its summary is usually within - // [1, 1 + 1e-5]. By setting SCALE_ERROR_LIMIT to 1e-5, We can identify - // events monitored all the time in most cases while keeping the report - // error rate <= 1e-5. - constexpr double SCALE_ERROR_LIMIT = 1e-5; - return (fabs(scale - 1.0) < SCALE_ERROR_LIMIT); - } }; static const std::unordered_map<std::string_view, std::pair<std::string_view, std::string_view>> @@ -169,9 +169,7 @@ static const std::unordered_map<std::string_view, std::pair<std::string_view, st class CounterSummaries { public: explicit CounterSummaries(bool csv) : csv_(csv) {} - void AddSummary(const CounterSummary& summary) { - summaries_.push_back(summary); - } + std::vector<CounterSummary>& Summaries() { return summaries_; } const CounterSummary* FindSummary(const std::string& type_name, const std::string& modifier) { @@ -195,9 +193,8 @@ class CounterSummaries { const CounterSummary* other = FindSummary(s.type_name, "k"); if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) { if (FindSummary(s.type_name, "") == nullptr) { - AddSummary(CounterSummary(s.type_name, "", s.group_id, - s.count + other->count, s.scale, true, - csv_)); + Summaries().emplace_back(s.type_name, "", s.group_id, s.count + other->count, s.scale, + true, csv_); } } } @@ -334,6 +331,48 @@ class CounterSummaries { bool csv_; }; +// devfreq may use performance counters to calculate memory latency (as in +// drivers/devfreq/arm-memlat-mon.c). Hopefully we can get more available counters by asking devfreq +// to not use the memory latency governor temporarily. +class DevfreqCounters { + public: + bool Use() { + if (!IsRoot()) { + LOG(ERROR) << "--use-devfreq-counters needs root permission to set devfreq governors"; + return false; + } + std::string devfreq_dir = "/sys/class/devfreq/"; + for (auto& name : GetSubDirs(devfreq_dir)) { + std::string governor_path = devfreq_dir + name + "/governor"; + if (IsRegularFile(governor_path)) { + std::string governor; + if (!android::base::ReadFileToString(governor_path, &governor)) { + LOG(ERROR) << "failed to read " << governor_path; + return false; + } + governor = android::base::Trim(governor); + if (governor == "mem_latency") { + if (!android::base::WriteStringToFile("performance", governor_path)) { + PLOG(ERROR) << "failed to write " << governor_path; + return false; + } + mem_latency_governor_paths_.emplace_back(std::move(governor_path)); + } + } + } + return true; + } + + ~DevfreqCounters() { + for (auto& path : mem_latency_governor_paths_) { + android::base::WriteStringToFile("mem_latency", path); + } + } + + private: + std::vector<std::string> mem_latency_governor_paths_; +}; + class StatCommand : public Command { public: StatCommand() @@ -378,6 +417,14 @@ class StatCommand : public Command { "-o output_filename Write report to output_filename instead of standard output.\n" "-p pid1,pid2,... Stat events on existing processes. Mutually exclusive with -a.\n" "-t tid1,tid2,... Stat events on existing threads. Mutually exclusive with -a.\n" +#if defined(__ANDROID__) +"--use-devfreq-counters On devices with Qualcomm SOCs, some hardware counters may be used\n" +" to monitor memory latency (in drivers/devfreq/arm-memlat-mon.c),\n" +" making fewer counters available to users. This option asks devfreq\n" +" to temporarily release counters by replacing memory-latency governor\n" +" with performance governor. It affects memory latency during profiling,\n" +" and may cause wedged power if simpleperf is killed in between.\n" +#endif "--verbose Show result in verbose mode.\n" #if 0 // Below options are only used internally and shouldn't be visible to the public. @@ -426,6 +473,7 @@ class StatCommand : public Command { std::string app_package_name_; bool in_app_context_; android::base::unique_fd stop_signal_fd_; + bool use_devfreq_counters_ = false; }; bool StatCommand::Run(const std::vector<std::string>& args) { @@ -444,6 +492,12 @@ bool StatCommand::Run(const std::vector<std::string>& args) { output_filename_, !event_selection_set_.GetTracepointEvents().empty()); } } + DevfreqCounters devfreq_counters; + if (use_devfreq_counters_) { + if (!devfreq_counters.Use()) { + return false; + } + } if (event_selection_set_.empty()) { if (!AddDefaultMeasuredEventTypes()) { return false; @@ -665,6 +719,10 @@ bool StatCommand::ParseOptions(const std::vector<std::string>& args, if (!SetTracepointEventsFilePath(args[i])) { return false; } +#if defined(__ANDROID__) + } else if (args[i] == "--use-devfreq-counters") { + use_devfreq_counters_ = true; +#endif } else if (args[i] == "--verbose") { verbose_mode_ = true; } else { @@ -744,6 +802,7 @@ bool StatCommand::ShowCounters(const std::vector<CountersInfo>& counters, } } + bool counters_always_available = true; CounterSummaries summaries(csv_); for (size_t i = 0; i < counters.size(); ++i) { const CountersInfo& counters_info = counters[i]; @@ -768,9 +827,9 @@ bool StatCommand::ShowCounters(const std::vector<CountersInfo>& counters, if (sum.time_running < sum.time_enabled && sum.time_running != 0) { scale = static_cast<double>(sum.time_enabled) / sum.time_running; } - summaries.AddSummary( - CounterSummary(counters_info.event_name, counters_info.event_modifier, - counters_info.group_id, sum.value, scale, false, csv_)); + summaries.Summaries().emplace_back(counters_info.event_name, counters_info.event_modifier, + counters_info.group_id, sum.value, scale, false, csv_); + counters_always_available &= summaries.Summaries().back().IsMonitoredAllTheTime(); } summaries.AutoGenerateSummaries(); summaries.GenerateComments(duration_in_sec); @@ -780,6 +839,11 @@ bool StatCommand::ShowCounters(const std::vector<CountersInfo>& counters, fprintf(fp, "Total test time,%lf,seconds,\n", duration_in_sec); else fprintf(fp, "\nTotal test time: %lf seconds.\n", duration_in_sec); + + if (!counters_always_available) { + LOG(WARNING) << "Some hardware counters are not always available (scale < 100%). " + << "Try --use-devfreq-counters if on a rooted device."; + } return true; } diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp index ecc7404e..3668cb91 100644 --- a/simpleperf/cmd_stat_test.cpp +++ b/simpleperf/cmd_stat_test.cpp @@ -303,3 +303,11 @@ TEST(stat_cmd, app_option_for_profileable_app) { TEST_REQUIRE_APPS(); TestStatingApps("com.android.simpleperf.profileable"); } + +TEST(stat_cmd, use_devfreq_counters_option) { +#if defined(__ANDROID__) + TEST_IN_ROOT(StatCmd()->Run({"--use-devfreq-counters", "sleep", "0.1"})); +#else + GTEST_LOG_(INFO) << "This test tests an option only available on Android."; +#endif +} |