From 876f3503119fa6ea21b85990b7f8b5f5abcdd1b0 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Thu, 24 Mar 2016 16:16:34 +0000 Subject: [PATCH] Extend profman to be able to dump profile content. With the move to binary format it gets harder to debug profiles. This adds a simple dumping mechanism to make profiles human readable. Bug: 27600652 (cherry picked from commit 54196728c25421e72d0009cac4c3145a0da18a58) Change-Id: I73148fe9e24f30089e9f0fb383e9f6f6c61a46e5 --- profman/profman.cc | 50 ++++++++++++++++++++++++++++++++--- runtime/jit/offline_profiling_info.cc | 32 ++++++++++++++-------- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/profman/profman.cc b/profman/profman.cc index 7c9e449ed..3e632bce8 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -14,12 +14,14 @@ * limitations under the License. */ +#include "errno.h" #include #include #include #include #include +#include #include #include @@ -68,6 +70,9 @@ NO_RETURN static void Usage(const char *fmt, ...) { UsageError("Command: %s", CommandLine().c_str()); UsageError("Usage: profman [options]..."); UsageError(""); + UsageError(" --dump-info-for=: dumps the content of the profile file"); + UsageError(" to standard output in a human readable form."); + UsageError(""); UsageError(" --profile-file=: specify profiler output file to use for compilation."); UsageError(" Can be specified multiple time, in which case the data from the different"); UsageError(" profiles will be aggregated."); @@ -117,9 +122,11 @@ class ProfMan FINAL { const StringPiece option(argv[i]); const bool log_options = false; if (log_options) { - LOG(INFO) << "patchoat: option[" << i << "]=" << argv[i]; + LOG(INFO) << "profman: option[" << i << "]=" << argv[i]; } - if (option.starts_with("--profile-file=")) { + if (option.starts_with("--dump-info-for=")) { + dump_info_for_ = option.substr(strlen("--dump-info-for=")).ToString(); + } else if (option.starts_with("--profile-file=")) { profile_files_.push_back(option.substr(strlen("--profile-file=")).ToString()); } else if (option.starts_with("--profile-file-fd=")) { ParseFdForCollection(option, "--profile-file-fd", &profile_files_fd_); @@ -132,13 +139,23 @@ class ProfMan FINAL { } } - if (profile_files_.empty() && profile_files_fd_.empty()) { + bool has_profiles = !profile_files_.empty() || !profile_files_fd_.empty(); + bool has_reference_profile = !reference_profile_file_.empty() || + (reference_profile_file_fd_ != -1); + + if (!dump_info_for_.empty()) { + if (has_profiles || has_reference_profile) { + Usage("dump-info-for cannot be specified together with other options"); + } + return; + } + if (!has_profiles) { Usage("No profile files specified."); } if (!profile_files_.empty() && !profile_files_fd_.empty()) { Usage("Profile files should not be specified with both --profile-file-fd and --profile-file"); } - if (!reference_profile_file_.empty() && (reference_profile_file_fd_ != -1)) { + if (!has_reference_profile) { Usage("--reference-profile-file-fd should only be supplied with --profile-file-fd"); } if (reference_profile_file_.empty() && (reference_profile_file_fd_ == -1)) { @@ -160,6 +177,27 @@ class ProfMan FINAL { return result; } + int DumpProfileInfo() { + int fd = open(dump_info_for_.c_str(), O_RDWR); + if (fd < 0) { + std::cerr << "Cannot open " << dump_info_for_ << strerror(errno); + return -1; + } + ProfileCompilationInfo info; + if (!info.Load(fd)) { + std::cerr << "Cannot load profile info from " << dump_info_for_; + return -1; + } + std::string dump = info.DumpInfo(/*dex_files*/ nullptr); + info.Save(fd); + std::cout << dump << "\n"; + return 0; + } + + bool ShouldOnlyDumpProfile() { + return !dump_info_for_.empty(); + } + private: static void ParseFdForCollection(const StringPiece& option, const char* arg_name, @@ -186,6 +224,7 @@ class ProfMan FINAL { std::string reference_profile_file_; int reference_profile_file_fd_; uint64_t start_ns_; + std::string dump_info_for_; }; // See ProfileAssistant::ProcessingResult for return codes. @@ -195,6 +234,9 @@ static int profman(int argc, char** argv) { // Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError. profman.ParseArgs(argc, argv); + if (profman.ShouldOnlyDumpProfile()) { + return profman.DumpProfileInfo(); + } // Process profile information and assess if we need to do a profile guided compilation. // This operation involves I/O. return profman.ProcessProfiles(); diff --git a/runtime/jit/offline_profiling_info.cc b/runtime/jit/offline_profiling_info.cc index 4ecb9265a..fa71905be 100644 --- a/runtime/jit/offline_profiling_info.cc +++ b/runtime/jit/offline_profiling_info.cc @@ -616,19 +616,29 @@ std::string ProfileCompilationInfo::DumpInfo(const std::vector* std::string multidex_suffix = DexFile::GetMultiDexSuffix(location); os << (multidex_suffix.empty() ? kFirstDexFileKeySubstitute : multidex_suffix); } - for (const auto method_it : dex_data.method_set) { - if (dex_files != nullptr) { - const DexFile* dex_file = nullptr; - for (size_t i = 0; i < dex_files->size(); i++) { - if (location == (*dex_files)[i]->GetLocation()) { - dex_file = (*dex_files)[i]; - } - } - if (dex_file != nullptr) { - os << "\n " << PrettyMethod(method_it, *dex_file, true); + const DexFile* dex_file = nullptr; + if (dex_files != nullptr) { + for (size_t i = 0; i < dex_files->size(); i++) { + if (location == (*dex_files)[i]->GetLocation()) { + dex_file = (*dex_files)[i]; } } - os << ", " << method_it; + } + os << "\n\tmethods: "; + for (const auto method_it : dex_data.method_set) { + if (dex_file != nullptr) { + os << "\n\t\t" << PrettyMethod(method_it, *dex_file, true); + } else { + os << method_it << ","; + } + } + os << "\n\tclasses: "; + for (const auto class_it : dex_data.class_set) { + if (dex_file != nullptr) { + os << "\n\t\t" << PrettyType(class_it, *dex_file); + } else { + os << class_it << ","; + } } } return os.str(); -- 2.11.0