summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-06-05 07:31:02 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-06-05 07:31:02 +0000
commita9e7a641a7b470263cb1b3db92f4e11c30272ce8 (patch)
treea9473a50aaeeaf05d67a40e19222d84330c64613
parent273d5cd1f9c68d043a4075f70155ac6ca259f918 (diff)
parent35eed0a24fa16f20b76bd1c3901ad2a9020ca097 (diff)
downloadextras-a9e7a641a7b470263cb1b3db92f4e11c30272ce8.tar.gz
release-request-a2143a0f-bf92-4fa8-ad68-7346e7505126-for-git_oc-dr1-release-4067638 snap-temp-L84900000070511178
Change-Id: Icd625305879f272b46476576a4cd19f0d745f3ea
-rw-r--r--simpleperf/cmd_report_sample.cpp47
-rw-r--r--simpleperf/cmd_report_sample_test.cpp12
-rw-r--r--simpleperf/environment.cpp7
-rw-r--r--simpleperf/report_sample.proto7
-rw-r--r--simpleperf/scripts/app_profiler.py5
-rw-r--r--simpleperf/scripts/utils.py13
-rw-r--r--simpleperf/thread_tree.cpp8
-rw-r--r--simpleperf/thread_tree.h1
8 files changed, 81 insertions, 19 deletions
diff --git a/simpleperf/cmd_report_sample.cpp b/simpleperf/cmd_report_sample.cpp
index f43f6821..73af7d90 100644
--- a/simpleperf/cmd_report_sample.cpp
+++ b/simpleperf/cmd_report_sample.cpp
@@ -92,8 +92,10 @@ class ReportSampleCommand : public Command {
uint64_t* pvaddr_in_file, uint32_t* pfile_id, int32_t* psymbol_id);
bool GetCallEntry(const ThreadEntry* thread, bool in_kernel, uint64_t ip, bool omit_unknown_dso,
uint64_t* pvaddr_in_file, Dso** pdso, const Symbol** psymbol);
+ bool WriteRecordInProtobuf(proto::Record& proto_record);
bool PrintLostSituationInProtobuf();
bool PrintFileInfoInProtobuf();
+ bool PrintThreadInfoInProtobuf();
bool PrintSampleRecord(const SampleRecord& record);
void PrintLostSituation();
@@ -178,6 +180,9 @@ bool ReportSampleCommand::Run(const std::vector<std::string>& args) {
if (!PrintFileInfoInProtobuf()) {
return false;
}
+ if (!PrintThreadInfoInProtobuf()) {
+ return false;
+ }
coded_os_->WriteLittleEndian32(0);
if (coded_os_->HadError()) {
LOG(ERROR) << "print protobuf report failed";
@@ -313,6 +318,12 @@ bool ReportSampleCommand::DumpProtobufReport(const std::string& filename) {
return false;
}
files.push_back(file.symbol_size());
+ } else if (proto_record.has_thread()) {
+ auto& thread = proto_record.thread();
+ FprintIndented(report_fp_, 0, "thread:\n");
+ FprintIndented(report_fp_, 1, "thread_id: %u\n", thread.thread_id());
+ FprintIndented(report_fp_, 1, "process_id: %u\n", thread.process_id());
+ FprintIndented(report_fp_, 1, "thread_name: %s\n", thread.thread_name().c_str());
} else {
LOG(ERROR) << "unexpected record type ";
return false;
@@ -404,9 +415,13 @@ bool ReportSampleCommand::PrintSampleRecordInProtobuf(const SampleRecord& r) {
}
}
}
+ return WriteRecordInProtobuf(proto_record);
+}
+
+bool ReportSampleCommand::WriteRecordInProtobuf(proto::Record& proto_record) {
coded_os_->WriteLittleEndian32(proto_record.ByteSize());
if (!proto_record.SerializeToCodedStream(coded_os_)) {
- LOG(ERROR) << "failed to write sample to protobuf";
+ LOG(ERROR) << "failed to write record to protobuf";
return false;
}
return true;
@@ -458,12 +473,7 @@ bool ReportSampleCommand::PrintLostSituationInProtobuf() {
proto::LostSituation* lost = proto_record.mutable_lost();
lost->set_sample_count(sample_count_);
lost->set_lost_count(lost_count_);
- coded_os_->WriteLittleEndian32(proto_record.ByteSize());
- if (!proto_record.SerializeToCodedStream(coded_os_)) {
- LOG(ERROR) << "failed to write lost situation to protobuf";
- return false;
- }
- return true;
+ return WriteRecordInProtobuf(proto_record);
}
static bool CompareDsoByDumpId(Dso* d1, Dso* d2) {
@@ -500,9 +510,26 @@ bool ReportSampleCommand::PrintFileInfoInProtobuf() {
std::string* symbol = file->add_symbol();
*symbol = sym->DemangledName();
}
- coded_os_->WriteLittleEndian32(proto_record.ByteSize());
- if (!proto_record.SerializeToCodedStream(coded_os_)) {
- LOG(ERROR) << "failed to write file info to protobuf";
+ if (!WriteRecordInProtobuf(proto_record)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ReportSampleCommand::PrintThreadInfoInProtobuf() {
+ std::vector<const ThreadEntry*> threads = thread_tree_.GetAllThreads();
+ auto compare_thread_id = [](const ThreadEntry* t1, const ThreadEntry* t2) {
+ return t1->tid < t2->tid;
+ };
+ std::sort(threads.begin(), threads.end(), compare_thread_id);
+ for (auto& thread : threads) {
+ proto::Record proto_record;
+ proto::Thread* proto_thread = proto_record.mutable_thread();
+ proto_thread->set_thread_id(thread->tid);
+ proto_thread->set_process_id(thread->pid);
+ proto_thread->set_thread_name(thread->comm);
+ if (!WriteRecordInProtobuf(proto_record)) {
return false;
}
}
diff --git a/simpleperf/cmd_report_sample_test.cpp b/simpleperf/cmd_report_sample_test.cpp
index 3e92396d..2a712be4 100644
--- a/simpleperf/cmd_report_sample_test.cpp
+++ b/simpleperf/cmd_report_sample_test.cpp
@@ -79,3 +79,15 @@ TEST(cmd_report_sample, sample_has_event_count) {
ASSERT_TRUE(android::base::ReadFileToString(tmpfile2.path, &data));
ASSERT_NE(data.find("event_count:"), std::string::npos);
}
+
+TEST(cmd_report_sample, has_thread_record) {
+ TemporaryFile tmpfile;
+ TemporaryFile tmpfile2;
+ ASSERT_TRUE(ReportSampleCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_SYMBOLS),
+ "-o", tmpfile.path, "--protobuf"}));
+ ASSERT_TRUE(ReportSampleCmd()->Run(
+ {"--dump-protobuf-report", tmpfile.path, "-o", tmpfile2.path}));
+ std::string data;
+ ASSERT_TRUE(android::base::ReadFileToString(tmpfile2.path, &data));
+ ASSERT_NE(data.find("thread:"), std::string::npos);
+}
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index d0cb8351..7fff85f1 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -361,8 +361,11 @@ static const char* GetLimitLevelDescription(int limit_level) {
}
bool CheckPerfEventLimit() {
- // root is not limited by /proc/sys/kernel/perf_event_paranoid.
- if (IsRoot()) {
+ // Root is not limited by /proc/sys/kernel/perf_event_paranoid. However, the monitored threads
+ // may create child processes not running as root. To make sure the child processes have
+ // enough permission to create inherited tracepoint events, write -1 to perf_event_paranoid.
+ // See http://b/62230699.
+ if (IsRoot() && android::base::WriteStringToFile("-1", "/proc/sys/kernel/perf_event_paranoid")) {
return true;
}
int limit_level;
diff --git a/simpleperf/report_sample.proto b/simpleperf/report_sample.proto
index 5e1d8605..a40f8032 100644
--- a/simpleperf/report_sample.proto
+++ b/simpleperf/report_sample.proto
@@ -59,10 +59,17 @@ message File {
repeated string symbol = 3;
}
+message Thread {
+ optional uint32 thread_id = 1;
+ optional uint32 process_id = 2;
+ optional string thread_name = 3;
+}
+
message Record {
oneof record_data {
Sample sample = 1;
LostSituation lost = 2;
File file = 3;
+ Thread thread = 4;
}
} \ No newline at end of file
diff --git a/simpleperf/scripts/app_profiler.py b/simpleperf/scripts/app_profiler.py
index 05e9534f..ea181f16 100644
--- a/simpleperf/scripts/app_profiler.py
+++ b/simpleperf/scripts/app_profiler.py
@@ -271,10 +271,7 @@ class AppProfiler(object):
def collect_profiling_data(self):
- self.run_in_app_dir(['chmod', 'a+rw', 'perf.data'])
- self.adb.check_run(['shell', 'cp',
- '/data/data/%s/perf.data' % self.config['app_package_name'], '/data/local/tmp'])
- self.adb.check_run(['pull', '/data/local/tmp/perf.data', self.config['perf_data_path']])
+ self.run_in_app_dir(['cat', 'perf.data', '>' + self.config['perf_data_path']])
config = copy.copy(self.config)
config['symfs_dirs'] = []
if self.config['native_lib_dir']:
diff --git a/simpleperf/scripts/utils.py b/simpleperf/scripts/utils.py
index 01853744..5474676d 100644
--- a/simpleperf/scripts/utils.py
+++ b/simpleperf/scripts/utils.py
@@ -107,9 +107,16 @@ class AdbHelper(object):
def run_and_return_output(self, adb_args):
adb_args = [self.adb_path] + adb_args
log_debug('run adb cmd: %s' % adb_args)
- subproc = subprocess.Popen(adb_args, stdout=subprocess.PIPE)
- (stdoutdata, _) = subproc.communicate()
- result = (subproc.returncode == 0)
+ if adb_args[-1][0] == '>':
+ stdout_file = adb_args[-1][1:]
+ with open(stdout_file, 'wb') as stdout_fh:
+ returncode = subprocess.call(adb_args[:-1], stdout=stdout_fh)
+ stdoutdata = ''
+ else:
+ subproc = subprocess.Popen(adb_args, stdout=subprocess.PIPE)
+ (stdoutdata, _) = subproc.communicate()
+ returncode = subproc.returncode
+ result = (returncode == 0)
if stdoutdata:
stdoutdata = bytes_to_str(stdoutdata)
log_debug(stdoutdata)
diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp
index a6f86a8a..92a8a8fe 100644
--- a/simpleperf/thread_tree.cpp
+++ b/simpleperf/thread_tree.cpp
@@ -327,4 +327,12 @@ std::vector<Dso*> ThreadTree::GetAllDsos() const {
return result;
}
+std::vector<const ThreadEntry*> ThreadTree::GetAllThreads() const {
+ std::vector<const ThreadEntry*> threads;
+ for (auto& pair : thread_tree_) {
+ threads.push_back(pair.second.get());
+ }
+ return threads;
+}
+
} // namespace simpleperf
diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h
index 8df6b7ba..621bc467 100644
--- a/simpleperf/thread_tree.h
+++ b/simpleperf/thread_tree.h
@@ -119,6 +119,7 @@ class ThreadTree {
void Update(const Record& record);
std::vector<Dso*> GetAllDsos() const;
+ std::vector<const ThreadEntry*> GetAllThreads() const;
private:
ThreadEntry* CreateThread(int pid, int tid);