diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-05 07:31:02 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-05 07:31:02 +0000 |
commit | a9e7a641a7b470263cb1b3db92f4e11c30272ce8 (patch) | |
tree | a9473a50aaeeaf05d67a40e19222d84330c64613 | |
parent | 273d5cd1f9c68d043a4075f70155ac6ca259f918 (diff) | |
parent | 35eed0a24fa16f20b76bd1c3901ad2a9020ca097 (diff) | |
download | extras-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.cpp | 47 | ||||
-rw-r--r-- | simpleperf/cmd_report_sample_test.cpp | 12 | ||||
-rw-r--r-- | simpleperf/environment.cpp | 7 | ||||
-rw-r--r-- | simpleperf/report_sample.proto | 7 | ||||
-rw-r--r-- | simpleperf/scripts/app_profiler.py | 5 | ||||
-rw-r--r-- | simpleperf/scripts/utils.py | 13 | ||||
-rw-r--r-- | simpleperf/thread_tree.cpp | 8 | ||||
-rw-r--r-- | simpleperf/thread_tree.h | 1 |
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); |