summaryrefslogtreecommitdiff
path: root/simpleperf/cmd_record.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2018-07-16 14:04:49 -0700
committerYabin Cui <yabinc@google.com>2018-07-16 17:46:11 -0700
commit2db05b4b3d209ae184ecb9dccb1d7925c3357abd (patch)
treeac6f31c2b507d7c342a6aa4e978770bcac52b425 /simpleperf/cmd_record.cpp
parent2ce2fa7eed139891406e4a5662a5481c3a376b54 (diff)
downloadextras-2db05b4b3d209ae184ecb9dccb1d7925c3357abd.tar.gz
simpleperf: prefer to use mmap2 records instead of mmap records.
When doing system wide recording, simpleperf spents a lot of time in calling ApkInspector::FindElfInApkByOffset() in UpdateMmapRecordForEmbeddedPath() in cmd_record.cpp (about 35% main thread time). This is because app processes map many files in the apk into the memory. Actually we only need to change the maps of executable files in the apk. However, mmap record doesn't show whether the mapped file is executable. So switch to mmap2 record when possible. mmap2 record is supported starting from kernel 3.16, and dumps more info than mmap record, like the protect flag of the map. After switching to mmap2 records, the cost of calling ApkInspector::FindElfInApkByOffset() is decreased to about 1% main thread time. Also switch to dump mmap and comm records only for the first event type. Also avoid using IsRegularFile() in IsMappingOnlyExistInMemory, which saves about 3% main thread time. Also add a test to request mmap2 record support in Q. Bug: none Test: run simpleperf for system wide recording manually. Test: run simpleperf_unit_test. Change-Id: Ib0f42f509cb10b3242503d54d048f9c90885affa
Diffstat (limited to 'simpleperf/cmd_record.cpp')
-rw-r--r--simpleperf/cmd_record.cpp27
1 files changed, 12 insertions, 15 deletions
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 44b05c4b..2597629f 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -1027,11 +1027,11 @@ bool RecordCommand::DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>&
const perf_event_attr& attr = *dumping_attr_id_.attr;
uint64_t event_id = dumping_attr_id_.ids[0];
for (const auto& map : thread_mmaps) {
- if (map.executable == 0 && !event_selection_set_.RecordNotExecutableMaps()) {
+ if (!(map.prot & PROT_EXEC) && !event_selection_set_.RecordNotExecutableMaps()) {
continue;
}
- MmapRecord record(attr, false, pid, pid, map.start_addr, map.len,
- map.pgoff, map.name, event_id, last_record_timestamp_);
+ Mmap2Record record(attr, false, pid, pid, map.start_addr, map.len,
+ map.pgoff, map.prot, map.name, event_id, last_record_timestamp_);
if (!ProcessRecord(&record)) {
return false;
}
@@ -1084,11 +1084,8 @@ bool RecordCommand::ProcessRecord(Record* record) {
}
template <typename MmapRecordType>
-bool IsMappingOnlyExistInMemory(MmapRecordType* record) {
- return !(record->InKernel() ||
- strcmp(record->filename, "[vdso]") == 0 ||
- strstr(record->filename, "!/") != nullptr ||
- IsRegularFile(record->filename));
+bool MapOnlyExistInMemory(MmapRecordType* record) {
+ return !record->InKernel() && MappedFileOnlyExistInMemory(record->filename);
}
bool RecordCommand::ShouldOmitRecord(Record* record) {
@@ -1100,9 +1097,9 @@ bool RecordCommand::ShouldOmitRecord(Record* record) {
// dalvik-jit-code-cache and other maps that only exist in memory.
switch (record->type()) {
case PERF_RECORD_MMAP:
- return IsMappingOnlyExistInMemory(static_cast<MmapRecord*>(record));
+ return MapOnlyExistInMemory(static_cast<MmapRecord*>(record));
case PERF_RECORD_MMAP2:
- return IsMappingOnlyExistInMemory(static_cast<Mmap2Record*>(record));
+ return MapOnlyExistInMemory(static_cast<Mmap2Record*>(record));
}
}
return false;
@@ -1200,8 +1197,7 @@ bool RecordCommand::ProcessJITDebugInfo(const std::vector<JITSymFile>& jit_symfi
}
template <class RecordType>
-void UpdateMmapRecordForEmbeddedPath(RecordType* record) {
- RecordType& r = *record;
+void UpdateMmapRecordForEmbeddedPath(RecordType& r, bool has_prot, uint32_t prot) {
if (r.InKernel()) {
return;
}
@@ -1213,7 +1209,7 @@ void UpdateMmapRecordForEmbeddedPath(RecordType* record) {
filename.resize(filename.size() - 10);
name_changed = true;
}
- if (r.data->pgoff != 0) {
+ if (r.data->pgoff != 0 && (!has_prot || (prot & PROT_EXEC))) {
// For the case of a shared library "foobar.so" embedded
// inside an APK, we rewrite the original MMAP from
// ["path.apk" offset=X] to ["path.apk!/foobar.so" offset=W]
@@ -1247,9 +1243,10 @@ void UpdateMmapRecordForEmbeddedPath(RecordType* record) {
void RecordCommand::UpdateRecordForEmbeddedPath(Record* record) {
if (record->type() == PERF_RECORD_MMAP) {
- UpdateMmapRecordForEmbeddedPath(static_cast<MmapRecord*>(record));
+ UpdateMmapRecordForEmbeddedPath(*static_cast<MmapRecord*>(record), false, 0);
} else if (record->type() == PERF_RECORD_MMAP2) {
- UpdateMmapRecordForEmbeddedPath(static_cast<Mmap2Record*>(record));
+ auto r = static_cast<Mmap2Record*>(record);
+ UpdateMmapRecordForEmbeddedPath(*r, true, r->data->prot);
}
}