summaryrefslogtreecommitdiff
path: root/simpleperf/report_lib_interface.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2018-04-13 11:23:06 -0700
committerYabin Cui <yabinc@google.com>2018-04-13 16:42:13 -0700
commit7c8847be25d52f69e88ef8ceba61b37a7d8aff39 (patch)
tree2a752ce7231cc6a3558676552013ba10c5f1af07 /simpleperf/report_lib_interface.cpp
parent7eb955eb189be1fbc375de9a6ab34fdafe3d8768 (diff)
downloadextras-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.cpp220
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 &current_event_; }
+ SymbolEntry* GetSymbolOfCurrentSample() { return current_symbol_; }
+ CallChain* GetCallChainOfCurrentSample() { return &current_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 &current_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 &current_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 &current_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 &current_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 &current_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);
}