diff options
author | Yabin Cui <yabinc@google.com> | 2018-04-13 11:23:06 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2018-04-13 16:42:13 -0700 |
commit | 7c8847be25d52f69e88ef8ceba61b37a7d8aff39 (patch) | |
tree | 2a752ce7231cc6a3558676552013ba10c5f1af07 /simpleperf/report_lib_interface.cpp | |
parent | 7eb955eb189be1fbc375de9a6ab34fdafe3d8768 (diff) | |
download | extras-7c8847be25d52f69e88ef8ceba61b37a7d8aff39.tar.gz |
simpleperf: remove Java interpreter frames by default.
In the callchains of interpreted Java code, two Java frames are
separated by several interpreter frames, which make it harder for
users to find Java frames. So this patch removes Java interpreter
frames by default in report-sample command output and
report_lib_interface. But it also provides the ability to show
Java interpreter frames via --show-art-frames option.
Bug: http://b/73126888
Test: run simpleperf_unit_test.
Test: run test.py.
Change-Id: I9a89e2f6679dc1455df8c669628fce198ae7d576
Diffstat (limited to 'simpleperf/report_lib_interface.cpp')
-rw-r--r-- | simpleperf/report_lib_interface.cpp | 220 |
1 files changed, 94 insertions, 126 deletions
diff --git a/simpleperf/report_lib_interface.cpp b/simpleperf/report_lib_interface.cpp index e3af8a88..0b2870c4 100644 --- a/simpleperf/report_lib_interface.cpp +++ b/simpleperf/report_lib_interface.cpp @@ -19,6 +19,7 @@ #include <android-base/logging.h> #include <android-base/file.h> +#include <android-base/strings.h> #include "dso.h" #include "event_attr.h" @@ -90,6 +91,7 @@ bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT; bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT; bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT; void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT; +void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT; Sample* GetNextSample(ReportLib* report_lib) EXPORT; Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT; @@ -105,13 +107,6 @@ struct EventAttrWithName { std::string name; }; -enum { - UPDATE_FLAG_OF_SAMPLE = 1 << 0, - UPDATE_FLAG_OF_EVENT = 1 << 1, - UPDATE_FLAG_OF_SYMBOL = 1 << 2, - UPDATE_FLAG_OF_CALLCHAIN = 1 << 3, -}; - class ReportLib { public: ReportLib() @@ -119,8 +114,8 @@ class ReportLib { new android::base::ScopedLogSeverity(android::base::INFO)), record_filename_("perf.data"), current_thread_(nullptr), - update_flag_(0), - trace_offcpu_(false) { + trace_offcpu_(false), + show_art_frames_(false) { } bool SetLogSeverity(const char* log_level); @@ -135,17 +130,20 @@ class ReportLib { bool SetKallsymsFile(const char* kallsyms_file); void ShowIpForUnknownSymbol() { thread_tree_.ShowIpForUnknownSymbol(); } + void ShowArtFrames(bool show) { show_art_frames_ = show; } Sample* GetNextSample(); - Event* GetEventOfCurrentSample(); - SymbolEntry* GetSymbolOfCurrentSample(); - CallChain* GetCallChainOfCurrentSample(); + Event* GetEventOfCurrentSample() { return ¤t_event_; } + SymbolEntry* GetSymbolOfCurrentSample() { return current_symbol_; } + CallChain* GetCallChainOfCurrentSample() { return ¤t_callchain_; } const char* GetBuildIdForPath(const char* path); FeatureSection* GetFeatureSection(const char* feature_name); private: - Sample* GetCurrentSample(); + void SetCurrentSample(); + void SetEventOfCurrentSample(); + bool OpenRecordFileIfNecessary(); Mapping* AddMapping(const MapEntry& map); @@ -157,18 +155,18 @@ class ReportLib { const ThreadEntry* current_thread_; Sample current_sample_; Event current_event_; - SymbolEntry current_symbol_; + SymbolEntry* current_symbol_; CallChain current_callchain_; std::vector<std::unique_ptr<Mapping>> current_mappings_; std::vector<CallChainEntry> callchain_entries_; std::string build_id_string_; - int update_flag_; std::vector<EventAttrWithName> event_attrs_; std::unique_ptr<ScopedEventTypes> scoped_event_types_; bool trace_offcpu_; std::unordered_map<pid_t, std::unique_ptr<SampleRecord>> next_sample_cache_; FeatureSection feature_section_; std::vector<char> feature_section_data_; + bool show_art_frames_; }; bool ReportLib::SetLogSeverity(const char* log_level) { @@ -245,130 +243,96 @@ Sample* ReportLib::GetNextSample() { break; } } - update_flag_ = 0; - current_mappings_.clear(); - return GetCurrentSample(); + SetCurrentSample(); + return ¤t_sample_; } -Sample* ReportLib::GetCurrentSample() { - if (!(update_flag_ & UPDATE_FLAG_OF_SAMPLE)) { - SampleRecord& r = *current_record_; - current_sample_.ip = r.ip_data.ip; - current_sample_.pid = r.tid_data.pid; - current_sample_.tid = r.tid_data.tid; - current_thread_ = - thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid); - current_sample_.thread_comm = current_thread_->comm; - current_sample_.time = r.time_data.time; - current_sample_.in_kernel = r.InKernel(); - current_sample_.cpu = r.cpu_data.cpu; - if (trace_offcpu_) { - uint64_t next_time = std::max(next_sample_cache_[r.tid_data.tid]->time_data.time, - r.time_data.time + 1); - current_sample_.period = next_time - r.time_data.time; - } else { - current_sample_.period = r.period_data.period; - } - update_flag_ |= UPDATE_FLAG_OF_SAMPLE; +void ReportLib::SetCurrentSample() { + current_mappings_.clear(); + callchain_entries_.clear(); + SampleRecord& r = *current_record_; + current_sample_.ip = r.ip_data.ip; + current_sample_.pid = r.tid_data.pid; + current_sample_.tid = r.tid_data.tid; + current_thread_ = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid); + current_sample_.thread_comm = current_thread_->comm; + current_sample_.time = r.time_data.time; + current_sample_.in_kernel = r.InKernel(); + current_sample_.cpu = r.cpu_data.cpu; + if (trace_offcpu_) { + uint64_t next_time = std::max(next_sample_cache_[r.tid_data.tid]->time_data.time, + r.time_data.time + 1); + current_sample_.period = next_time - r.time_data.time; + } else { + current_sample_.period = r.period_data.period; } - return ¤t_sample_; -} -Event* ReportLib::GetEventOfCurrentSample() { - if (!(update_flag_ & UPDATE_FLAG_OF_EVENT)) { - if (event_attrs_.empty()) { - std::vector<EventAttrWithId> attrs = record_file_reader_->AttrSection(); - for (const auto& attr_with_id : attrs) { - EventAttrWithName attr; - attr.attr = *attr_with_id.attr; - attr.name = GetEventNameByAttr(attr.attr); - event_attrs_.push_back(attr); + size_t kernel_ip_count; + std::vector<uint64_t> ips = r.GetCallChain(&kernel_ip_count); + std::vector<std::pair<uint64_t, const MapEntry*>> ip_maps; + bool near_java_method = false; + auto is_map_for_interpreter = [](const MapEntry* map) { + return android::base::EndsWith(map->dso->Path(), "/libart.so"); + }; + for (size_t i = 0; i < ips.size(); ++i) { + const MapEntry* map = thread_tree_.FindMap(current_thread_, ips[i], i < kernel_ip_count); + if (!show_art_frames_) { + // Remove interpreter frames both before and after the Java frame. + if (map->dso->type() == DSO_DEX_FILE) { + near_java_method = true; + while (!ip_maps.empty() && is_map_for_interpreter(ip_maps.back().second)) { + ip_maps.pop_back(); + } + } else if (is_map_for_interpreter(map)){ + if (near_java_method) { + continue; + } + } else { + near_java_method = false; } } - size_t attr_index; - if (trace_offcpu_) { - // For trace-offcpu, we don't want to show event sched:sched_switch. - attr_index = 0; - } else { - attr_index = record_file_reader_->GetAttrIndexOfRecord(current_record_.get()); - } - current_event_.name = event_attrs_[attr_index].name.c_str(); - update_flag_ |= UPDATE_FLAG_OF_EVENT; + ip_maps.push_back(std::make_pair(ips[i], map)); } - return ¤t_event_; -} - -SymbolEntry* ReportLib::GetSymbolOfCurrentSample() { - if (!(update_flag_ & UPDATE_FLAG_OF_SYMBOL)) { - SampleRecord& r = *current_record_; - const MapEntry* map = - thread_tree_.FindMap(current_thread_, r.ip_data.ip, r.InKernel()); + for (auto& pair : ip_maps) { + uint64_t ip = pair.first; + const MapEntry* map = pair.second; uint64_t vaddr_in_file; - const Symbol* symbol = - thread_tree_.FindSymbol(map, r.ip_data.ip, &vaddr_in_file); - current_symbol_.dso_name = map->dso->Path().c_str(); - current_symbol_.vaddr_in_file = vaddr_in_file; - current_symbol_.symbol_name = symbol->DemangledName(); - current_symbol_.symbol_addr = symbol->addr; - current_symbol_.symbol_len = symbol->len; - current_symbol_.mapping = AddMapping(*map); - update_flag_ |= UPDATE_FLAG_OF_SYMBOL; + const Symbol* symbol = thread_tree_.FindSymbol(map, ip, &vaddr_in_file); + CallChainEntry entry; + entry.ip = ip; + entry.symbol.dso_name = map->dso->Path().c_str(); + entry.symbol.vaddr_in_file = vaddr_in_file; + entry.symbol.symbol_name = symbol->DemangledName(); + entry.symbol.symbol_addr = symbol->addr; + entry.symbol.symbol_len = symbol->len; + entry.symbol.mapping = AddMapping(*map); + callchain_entries_.push_back(entry); } - return ¤t_symbol_; + current_sample_.ip = callchain_entries_[0].ip; + current_symbol_ = &(callchain_entries_[0].symbol); + current_callchain_.nr = callchain_entries_.size() - 1; + current_callchain_.entries = &callchain_entries_[1]; + SetEventOfCurrentSample(); } -CallChain* ReportLib::GetCallChainOfCurrentSample() { - if (!(update_flag_ & UPDATE_FLAG_OF_CALLCHAIN)) { - SampleRecord& r = *current_record_; - callchain_entries_.clear(); - - if (r.sample_type & PERF_SAMPLE_CALLCHAIN) { - bool first_ip = true; - bool in_kernel = r.InKernel(); - for (uint64_t i = 0; i < r.callchain_data.ip_nr; ++i) { - uint64_t ip = r.callchain_data.ips[i]; - if (ip >= PERF_CONTEXT_MAX) { - switch (ip) { - case PERF_CONTEXT_KERNEL: - in_kernel = true; - break; - case PERF_CONTEXT_USER: - in_kernel = false; - break; - default: - LOG(DEBUG) << "Unexpected perf_context in callchain: " << std::hex - << ip; - } - } else { - if (first_ip) { - first_ip = false; - // Remove duplication with sample ip. - if (ip == r.ip_data.ip) { - continue; - } - } - const MapEntry* map = - thread_tree_.FindMap(current_thread_, ip, in_kernel); - uint64_t vaddr_in_file; - const Symbol* symbol = - thread_tree_.FindSymbol(map, ip, &vaddr_in_file); - CallChainEntry entry; - entry.ip = ip; - entry.symbol.dso_name = map->dso->Path().c_str(); - entry.symbol.vaddr_in_file = vaddr_in_file; - entry.symbol.symbol_name = symbol->DemangledName(); - entry.symbol.symbol_addr = symbol->addr; - entry.symbol.symbol_len = symbol->len; - entry.symbol.mapping = AddMapping(*map); - callchain_entries_.push_back(entry); - } - } +void ReportLib::SetEventOfCurrentSample() { + if (event_attrs_.empty()) { + std::vector<EventAttrWithId> attrs = record_file_reader_->AttrSection(); + for (const auto& attr_with_id : attrs) { + EventAttrWithName attr; + attr.attr = *attr_with_id.attr; + attr.name = GetEventNameByAttr(attr.attr); + event_attrs_.push_back(attr); } - current_callchain_.nr = callchain_entries_.size(); - current_callchain_.entries = callchain_entries_.data(); - update_flag_ |= UPDATE_FLAG_OF_CALLCHAIN; } - return ¤t_callchain_; + size_t attr_index; + if (trace_offcpu_) { + // For trace-offcpu, we don't want to show event sched:sched_switch. + attr_index = 0; + } else { + attr_index = record_file_reader_->GetAttrIndexOfRecord(current_record_.get()); + } + current_event_.name = event_attrs_[attr_index].name.c_str(); } Mapping* ReportLib::AddMapping(const MapEntry& map) { @@ -432,6 +396,10 @@ void ShowIpForUnknownSymbol(ReportLib* report_lib) { return report_lib->ShowIpForUnknownSymbol(); } +void ShowArtFrames(ReportLib* report_lib, bool show) { + return report_lib->ShowArtFrames(show); +} + bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) { return report_lib->SetKallsymsFile(kallsyms_file); } |