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
diff --git a/profman/profman.cc b/profman/profman.cc
index 7c9e449..3e632bc 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -14,12 +14,14 @@
* limitations under the License.
*/
+#include "errno.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <iostream>
#include <string>
#include <vector>
@@ -68,6 +70,9 @@
UsageError("Command: %s", CommandLine().c_str());
UsageError("Usage: profman [options]...");
UsageError("");
+ UsageError(" --dump-info-for=<filename>: dumps the content of the profile file");
+ UsageError(" to standard output in a human readable form.");
+ UsageError("");
UsageError(" --profile-file=<filename>: 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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
// 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();