diff options
author | Yabin Cui <yabinc@google.com> | 2020-03-31 16:59:33 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2020-04-01 10:20:28 -0700 |
commit | 9611c7902783d35f36f5c9214c7cfea4b0af7a49 (patch) | |
tree | 9df13de2ad7e73254abd86ef50850d4fde9bff44 | |
parent | bf06df7d2d361ccca839813c54e2c9073c0c828e (diff) | |
download | extras-9611c7902783d35f36f5c9214c7cfea4b0af7a49.tar.gz |
simpleperf: move CounterSummaries definition to header file.
This is to test it in later CLs.
Bug: 152911261
Test: run simpleperf_unit_test.
Change-Id: I0cdad299654eb36db4a64363335bfa03e54ee7b1
(cherry picked from commit 5271aa719b7cae4cddc9f67803648f17f9b24018)
-rw-r--r-- | simpleperf/cmd_stat.cpp | 360 | ||||
-rw-r--r-- | simpleperf/cmd_stat_impl.h | 30 |
2 files changed, 202 insertions, 188 deletions
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp index c8712df7..3bfc635f 100644 --- a/simpleperf/cmd_stat.cpp +++ b/simpleperf/cmd_stat.cpp @@ -45,7 +45,7 @@ using namespace simpleperf; -namespace { +namespace simpleperf { static std::vector<std::string> default_measured_event_types{ "cpu-cycles", "stalled-cycles-frontend", "stalled-cycles-backend", @@ -90,236 +90,220 @@ static const std::unordered_map<std::string_view, std::pair<std::string_view, st {"raw-l2d-tlb-refill-rd", {"raw-l2d-tlb-rd", "level 2 data TLB refill rate, read"}}, }; -class CounterSummaries { - public: - explicit CounterSummaries(std::vector<CounterSummary>&& summaries, bool csv) - : summaries_(std::move(summaries)), csv_(csv) {} - const std::vector<CounterSummary>& Summaries() { return summaries_; } - - const CounterSummary* FindSummary(const std::string& type_name, const std::string& modifier, - const ThreadInfo* thread, int cpu) { - for (const auto& s : summaries_) { - if (s.type_name == type_name && s.modifier == modifier && s.thread == thread && - s.cpu == cpu) { - return &s; - } +const CounterSummary* CounterSummaries::FindSummary(const std::string& type_name, + const std::string& modifier, + const ThreadInfo* thread, int cpu) { + for (const auto& s : summaries_) { + if (s.type_name == type_name && s.modifier == modifier && s.thread == thread && s.cpu == cpu) { + return &s; } - return nullptr; - } - - // If we have two summaries monitoring the same event type at the same time, - // that one is for user space only, and the other is for kernel space only; - // then we can automatically generate a summary combining the two results. - // For example, a summary of branch-misses:u and a summary for branch-misses:k - // can generate a summary of branch-misses. - void AutoGenerateSummaries() { - for (size_t i = 0; i < summaries_.size(); ++i) { - const CounterSummary& s = summaries_[i]; - if (s.modifier == "u") { - const CounterSummary* other = FindSummary(s.type_name, "k", s.thread, s.cpu); - if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) { - if (FindSummary(s.type_name, "", s.thread, s.cpu) == nullptr) { - summaries_.emplace_back(s.type_name, "", s.group_id, s.thread, s.cpu, - s.count + other->count, s.scale, true, csv_); - } + } + return nullptr; +} + +void CounterSummaries::AutoGenerateSummaries() { + for (size_t i = 0; i < summaries_.size(); ++i) { + const CounterSummary& s = summaries_[i]; + if (s.modifier == "u") { + const CounterSummary* other = FindSummary(s.type_name, "k", s.thread, s.cpu); + if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) { + if (FindSummary(s.type_name, "", s.thread, s.cpu) == nullptr) { + summaries_.emplace_back(s.type_name, "", s.group_id, s.thread, s.cpu, + s.count + other->count, s.scale, true, csv_); } } } } +} - void GenerateComments(double duration_in_sec) { - for (auto& s : summaries_) { - s.comment = GetCommentForSummary(s, duration_in_sec); - } +void CounterSummaries::GenerateComments(double duration_in_sec) { + for (auto& s : summaries_) { + s.comment = GetCommentForSummary(s, duration_in_sec); } +} - void Show(FILE* fp) { - if (csv_) { - ShowCSV(fp); - } else { - ShowText(fp); - } +void CounterSummaries::Show(FILE* fp) { + if (csv_) { + ShowCSV(fp); + } else { + ShowText(fp); } +} - void ShowCSV(FILE* fp) { - for (auto& s : summaries_) { - if (s.thread != nullptr) { - fprintf(fp, "%s,%d,%d,", s.thread->name.c_str(), s.thread->pid, s.thread->tid); - } - fprintf(fp, "%s,%s,%s,(%.0lf%%)%s\n", s.readable_count.c_str(), s.Name().c_str(), - s.comment.c_str(), 1.0 / s.scale * 100, (s.auto_generated ? " (generated)," : ",")); +void CounterSummaries::ShowCSV(FILE* fp) { + for (auto& s : summaries_) { + if (s.thread != nullptr) { + fprintf(fp, "%s,%d,%d,", s.thread->name.c_str(), s.thread->pid, s.thread->tid); } + fprintf(fp, "%s,%s,%s,(%.0lf%%)%s\n", s.readable_count.c_str(), s.Name().c_str(), + s.comment.c_str(), 1.0 / s.scale * 100, (s.auto_generated ? " (generated)," : ",")); } +} - void ShowText(FILE* fp) { - bool show_thread = !summaries_.empty() && summaries_[0].thread != nullptr; - bool show_cpu = !summaries_.empty() && summaries_[0].cpu != -1; - std::vector<std::string> titles; +void CounterSummaries::ShowText(FILE* fp) { + bool show_thread = !summaries_.empty() && summaries_[0].thread != nullptr; + bool show_cpu = !summaries_.empty() && summaries_[0].cpu != -1; + std::vector<std::string> titles; - if (show_thread) { - titles = {"thread_name", "pid", "tid"}; - } - if (show_cpu) { - titles.emplace_back("cpu"); - } - titles.emplace_back("count"); - titles.emplace_back("event_name"); - titles.emplace_back(" # percentage = event_run_time / enabled_time"); - - std::vector<size_t> width(titles.size(), 0); + if (show_thread) { + titles = {"thread_name", "pid", "tid"}; + } + if (show_cpu) { + titles.emplace_back("cpu"); + } + titles.emplace_back("count"); + titles.emplace_back("event_name"); + titles.emplace_back(" # percentage = event_run_time / enabled_time"); - auto adjust_width = [](size_t& w, size_t size) { - w = std::max(w, size); - }; + std::vector<size_t> width(titles.size(), 0); - // The last title is too long. Don't include it for width adjustment. - for (size_t i = 0; i + 1 < titles.size(); i++) { - adjust_width(width[i], titles[i].size()); - } + auto adjust_width = [](size_t& w, size_t size) { w = std::max(w, size); }; - for (auto& s : summaries_) { - size_t i = 0; - if (show_thread) { - adjust_width(width[i++], s.thread->name.size()); - adjust_width(width[i++], std::to_string(s.thread->pid).size()); - adjust_width(width[i++], std::to_string(s.thread->tid).size()); - } - if (show_cpu) { - adjust_width(width[i++], std::to_string(s.cpu).size()); - } - adjust_width(width[i++], s.readable_count.size()); - adjust_width(width[i++], s.Name().size()); - adjust_width(width[i++], s.comment.size()); - } + // The last title is too long. Don't include it for width adjustment. + for (size_t i = 0; i + 1 < titles.size(); i++) { + adjust_width(width[i], titles[i].size()); + } - fprintf(fp, "# "); - for (size_t i = 0; i < titles.size(); i++) { - if (titles[i] == "count") { - fprintf(fp, "%*s", static_cast<int>(width[i]), titles[i].c_str()); - } else { - fprintf(fp, "%-*s", static_cast<int>(width[i]), titles[i].c_str()); - } - if (i + 1 < titles.size()) { - fprintf(fp, " "); - } + for (auto& s : summaries_) { + size_t i = 0; + if (show_thread) { + adjust_width(width[i++], s.thread->name.size()); + adjust_width(width[i++], std::to_string(s.thread->pid).size()); + adjust_width(width[i++], std::to_string(s.thread->tid).size()); } - fprintf(fp, "\n"); - - for (auto& s : summaries_) { - size_t i = 0; - if (show_thread) { - fprintf(fp, " %-*s", static_cast<int>(width[i++]), s.thread->name.c_str()); - fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.thread->pid); - fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.thread->tid); - } - if (show_cpu) { - fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.cpu); - } - fprintf(fp, " %*s %-*s # %-*s (%.0lf%%)%s\n", - static_cast<int>(width[i]), s.readable_count.c_str(), - static_cast<int>(width[i+1]), s.Name().c_str(), - static_cast<int>(width[i+2]), s.comment.c_str(), - 1.0 / s.scale * 100, (s.auto_generated ? " (generated)" : "")); + if (show_cpu) { + adjust_width(width[i++], std::to_string(s.cpu).size()); } + adjust_width(width[i++], s.readable_count.size()); + adjust_width(width[i++], s.Name().size()); + adjust_width(width[i++], s.comment.size()); } - private: - std::string GetCommentForSummary(const CounterSummary& s, - double duration_in_sec) { - char sap_mid; - if (csv_) { - sap_mid = ','; + fprintf(fp, "# "); + for (size_t i = 0; i < titles.size(); i++) { + if (titles[i] == "count") { + fprintf(fp, "%*s", static_cast<int>(width[i]), titles[i].c_str()); } else { - sap_mid = ' '; + fprintf(fp, "%-*s", static_cast<int>(width[i]), titles[i].c_str()); } - if (s.type_name == "task-clock") { - double run_sec = s.count / 1e9; - double used_cpus = run_sec / (duration_in_sec / s.scale); - return android::base::StringPrintf("%lf%ccpus used", used_cpus, sap_mid); + if (i + 1 < titles.size()) { + fprintf(fp, " "); } - if (s.type_name == "cpu-clock") { - return ""; - } - if (s.type_name == "cpu-cycles") { - double running_time_in_sec; - if (!FindRunningTimeForSummary(s, &running_time_in_sec)) { - return ""; - } - double hz = s.count / (running_time_in_sec / s.scale); - return android::base::StringPrintf("%lf%cGHz", hz / 1e9, sap_mid); - } - if (s.type_name == "instructions" && s.count != 0) { - const CounterSummary* other = FindSummary("cpu-cycles", s.modifier, s.thread, s.cpu); - if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) { - double cpi = static_cast<double>(other->count) / s.count; - return android::base::StringPrintf("%lf%ccycles per instruction", cpi, - sap_mid); - } + } + fprintf(fp, "\n"); + + for (auto& s : summaries_) { + size_t i = 0; + if (show_thread) { + fprintf(fp, " %-*s", static_cast<int>(width[i++]), s.thread->name.c_str()); + fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.thread->pid); + fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.thread->tid); } - std::string rate_comment = GetRateComment(s, sap_mid); - if (!rate_comment.empty()) { - return rate_comment; + if (show_cpu) { + fprintf(fp, " %-*d", static_cast<int>(width[i++]), s.cpu); } + fprintf(fp, " %*s %-*s # %-*s (%.0lf%%)%s\n", static_cast<int>(width[i]), + s.readable_count.c_str(), static_cast<int>(width[i + 1]), s.Name().c_str(), + static_cast<int>(width[i + 2]), s.comment.c_str(), 1.0 / s.scale * 100, + (s.auto_generated ? " (generated)" : "")); + } +} + +std::string CounterSummaries::GetCommentForSummary(const CounterSummary& s, + double duration_in_sec) { + char sap_mid; + if (csv_) { + sap_mid = ','; + } else { + sap_mid = ' '; + } + if (s.type_name == "task-clock") { + double run_sec = s.count / 1e9; + double used_cpus = run_sec / (duration_in_sec / s.scale); + return android::base::StringPrintf("%lf%ccpus used", used_cpus, sap_mid); + } + if (s.type_name == "cpu-clock") { + return ""; + } + if (s.type_name == "cpu-cycles") { double running_time_in_sec; if (!FindRunningTimeForSummary(s, &running_time_in_sec)) { return ""; } - double rate = s.count / (running_time_in_sec / s.scale); - if (rate > 1e9) { - return android::base::StringPrintf("%.3lf%cG/sec", rate / 1e9, sap_mid); - } - if (rate > 1e6) { - return android::base::StringPrintf("%.3lf%cM/sec", rate / 1e6, sap_mid); - } - if (rate > 1e3) { - return android::base::StringPrintf("%.3lf%cK/sec", rate / 1e3, sap_mid); + double hz = s.count / (running_time_in_sec / s.scale); + return android::base::StringPrintf("%lf%cGHz", hz / 1e9, sap_mid); + } + if (s.type_name == "instructions" && s.count != 0) { + const CounterSummary* other = FindSummary("cpu-cycles", s.modifier, s.thread, s.cpu); + if (other != nullptr && other->IsMonitoredAtTheSameTime(s)) { + double cpi = static_cast<double>(other->count) / s.count; + return android::base::StringPrintf("%lf%ccycles per instruction", cpi, sap_mid); } - return android::base::StringPrintf("%.3lf%c/sec", rate, sap_mid); } + std::string rate_comment = GetRateComment(s, sap_mid); + if (!rate_comment.empty()) { + return rate_comment; + } + double running_time_in_sec; + if (!FindRunningTimeForSummary(s, &running_time_in_sec)) { + return ""; + } + double rate = s.count / (running_time_in_sec / s.scale); + if (rate > 1e9) { + return android::base::StringPrintf("%.3lf%cG/sec", rate / 1e9, sap_mid); + } + if (rate > 1e6) { + return android::base::StringPrintf("%.3lf%cM/sec", rate / 1e6, sap_mid); + } + if (rate > 1e3) { + return android::base::StringPrintf("%.3lf%cK/sec", rate / 1e3, sap_mid); + } + return android::base::StringPrintf("%.3lf%c/sec", rate, sap_mid); +} - std::string GetRateComment(const CounterSummary& s, char sep) { - std::string_view miss_event_name = s.type_name; - std::string event_name; - std::string rate_desc; - if (auto it = COMMON_EVENT_RATE_MAP.find(miss_event_name); it != COMMON_EVENT_RATE_MAP.end()) { +std::string CounterSummaries::GetRateComment(const CounterSummary& s, char sep) { + std::string_view miss_event_name = s.type_name; + std::string event_name; + std::string rate_desc; + if (auto it = COMMON_EVENT_RATE_MAP.find(miss_event_name); it != COMMON_EVENT_RATE_MAP.end()) { + event_name = it->second.first; + rate_desc = it->second.second; + } + if (event_name.empty() && (GetBuildArch() == ARCH_ARM || GetBuildArch() == ARCH_ARM64)) { + if (auto it = ARM_EVENT_RATE_MAP.find(miss_event_name); it != ARM_EVENT_RATE_MAP.end()) { event_name = it->second.first; rate_desc = it->second.second; } - if (event_name.empty() && (GetBuildArch() == ARCH_ARM || GetBuildArch() == ARCH_ARM64)) { - if (auto it = ARM_EVENT_RATE_MAP.find(miss_event_name); it != ARM_EVENT_RATE_MAP.end()) { - event_name = it->second.first; - rate_desc = it->second.second; - } - } - if (event_name.empty() && android::base::ConsumeSuffix(&miss_event_name, "-misses")) { - event_name = std::string(miss_event_name) + "s"; - rate_desc = "miss rate"; - } - if (!event_name.empty()) { - const CounterSummary* other = FindSummary(event_name, s.modifier, s.thread, s.cpu); - if (other != nullptr && other->IsMonitoredAtTheSameTime(s) && other->count != 0) { - double miss_rate = static_cast<double>(s.count) / other->count; - return android::base::StringPrintf("%f%%%c%s", miss_rate * 100, sep, rate_desc.c_str()); - } + } + if (event_name.empty() && android::base::ConsumeSuffix(&miss_event_name, "-misses")) { + event_name = std::string(miss_event_name) + "s"; + rate_desc = "miss rate"; + } + if (!event_name.empty()) { + const CounterSummary* other = FindSummary(event_name, s.modifier, s.thread, s.cpu); + if (other != nullptr && other->IsMonitoredAtTheSameTime(s) && other->count != 0) { + double miss_rate = static_cast<double>(s.count) / other->count; + return android::base::StringPrintf("%f%%%c%s", miss_rate * 100, sep, rate_desc.c_str()); } - return ""; } + return ""; +} - bool FindRunningTimeForSummary(const CounterSummary& summary, double* running_time_in_sec) { - for (auto& s : summaries_) { - if ((s.type_name == "task-clock" || s.type_name == "cpu-clock") && - s.IsMonitoredAtTheSameTime(summary) && s.count != 0u) { - *running_time_in_sec = s.count / 1e9; - return true; - } +bool CounterSummaries::FindRunningTimeForSummary(const CounterSummary& summary, + double* running_time_in_sec) { + for (auto& s : summaries_) { + if ((s.type_name == "task-clock" || s.type_name == "cpu-clock") && + s.IsMonitoredAtTheSameTime(summary) && s.count != 0u) { + *running_time_in_sec = s.count / 1e9; + return true; } - return false; } + return false; +} - private: - std::vector<CounterSummary> summaries_; - bool csv_; -}; +} // namespace simpleperf + +namespace { // 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 diff --git a/simpleperf/cmd_stat_impl.h b/simpleperf/cmd_stat_impl.h index 16dd091d..f8a751fe 100644 --- a/simpleperf/cmd_stat_impl.h +++ b/simpleperf/cmd_stat_impl.h @@ -243,4 +243,34 @@ class CounterSummaryBuilder { std::vector<CounterSummary> summaries_; }; +class CounterSummaries { + public: + explicit CounterSummaries(std::vector<CounterSummary>&& summaries, bool csv) + : summaries_(std::move(summaries)), csv_(csv) {} + const std::vector<CounterSummary>& Summaries() { return summaries_; } + + const CounterSummary* FindSummary(const std::string& type_name, const std::string& modifier, + const ThreadInfo* thread, int cpu); + + // If we have two summaries monitoring the same event type at the same time, + // that one is for user space only, and the other is for kernel space only; + // then we can automatically generate a summary combining the two results. + // For example, a summary of branch-misses:u and a summary for branch-misses:k + // can generate a summary of branch-misses. + void AutoGenerateSummaries(); + void GenerateComments(double duration_in_sec); + void Show(FILE* fp); + void ShowCSV(FILE* fp); + void ShowText(FILE* fp); + + private: + std::string GetCommentForSummary(const CounterSummary& s, double duration_in_sec); + std::string GetRateComment(const CounterSummary& s, char sep); + bool FindRunningTimeForSummary(const CounterSummary& summary, double* running_time_in_sec); + + private: + std::vector<CounterSummary> summaries_; + bool csv_; +}; + } // namespace simpleperf
\ No newline at end of file |