summaryrefslogtreecommitdiffstats
path: root/profman
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2018-01-22 19:22:24 -0800
committerCalin Juravle <calin@google.com>2018-01-24 12:14:47 -0800
commit2dba0ab8498e5ff3ba5be2e37e26310a661cf259 (patch)
tree4dcc90f214855c7521817f9809712726132d4a1e /profman
parent49971eb50c0213b7506bdd29954a6a4423e6426a (diff)
downloadart-2dba0ab8498e5ff3ba5be2e37e26310a661cf259.tar.gz
art-2dba0ab8498e5ff3ba5be2e37e26310a661cf259.tar.bz2
art-2dba0ab8498e5ff3ba5be2e37e26310a661cf259.zip
Enable profile key updates via profman
Allow profman to update the profile key in an existing profile based on new dex location. This is needed in order to support profiles for dex files that might move from their original profiling location (e.g. during install) The matching [profile key <-> dex_file] is done based on the dex checksum and the number of methods ids. If neither is a match then the profile key is not updated. If the new profile key would collide with an existing key (for a different dex) then the update will fail. Test: profile_compilation_info_test Bug: 30934496 Change-Id: Ic696b3f6fe9da2007421bf044d58a21c90fd9ee7
Diffstat (limited to 'profman')
-rw-r--r--profman/profman.cc50
1 files changed, 47 insertions, 3 deletions
diff --git a/profman/profman.cc b/profman/profman.cc
index 9f3e3b6ac5..ffc3c0170f 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -149,6 +149,10 @@ NO_RETURN static void Usage(const char *fmt, ...) {
UsageError(" --boot-image-sampled-method-threshold=<value>: minimum number of profiles a");
UsageError(" non-hot method needs to be in order to be hot in the output profile. The");
UsageError(" default is max int.");
+ UsageError(" --copy-and-update-profile-key: if present, profman will copy the profile from");
+ UsageError(" the file passed with --profile-fd(file) to the profile passed with");
+ UsageError(" --reference-profile-fd(file) and update at the same time the profile-key");
+ UsageError(" of entries corresponding to the apks passed with --apk(-fd).");
UsageError("");
exit(EXIT_FAILURE);
@@ -186,7 +190,8 @@ class ProfMan FINAL {
test_profile_method_percerntage_(kDefaultTestProfileMethodPercentage),
test_profile_class_percentage_(kDefaultTestProfileClassPercentage),
test_profile_seed_(NanoTime()),
- start_ns_(NanoTime()) {}
+ start_ns_(NanoTime()),
+ copy_and_update_profile_key_(false) {}
~ProfMan() {
LogCompletionTime();
@@ -302,11 +307,13 @@ class ProfMan FINAL {
"should only be used together");
}
ProfileAssistant::ProcessingResult result;
+
if (profile_files_.empty()) {
// The file doesn't need to be flushed here (ProcessProfiles will do it)
// so don't check the usage.
File file(reference_profile_file_fd_, false);
- result = ProfileAssistant::ProcessProfiles(profile_files_fd_, reference_profile_file_fd_);
+ result = ProfileAssistant::ProcessProfiles(profile_files_fd_,
+ reference_profile_file_fd_);
CloseAllFds(profile_files_fd_, "profile_files_fd_");
} else {
result = ProfileAssistant::ProcessProfiles(profile_files_, reference_profile_file_);
@@ -314,7 +321,7 @@ class ProfMan FINAL {
return result;
}
- void OpenApkFilesFromLocations(std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+ void OpenApkFilesFromLocations(std::vector<std::unique_ptr<const DexFile>>* dex_files) const {
bool use_apk_fd_list = !apks_fd_.empty();
if (use_apk_fd_list) {
// Get the APKs from the collection of FDs.
@@ -1070,6 +1077,42 @@ class ProfMan FINAL {
return !test_profile_.empty();
}
+ bool ShouldCopyAndUpdateProfileKey() const {
+ return copy_and_update_profile_key_;
+ }
+
+ bool CopyAndUpdateProfileKey() const {
+ // Validate that at least one profile file was passed, as well as a reference profile.
+ if (!(profile_files_.size() == 1 ^ profile_files_fd_.size() == 1)) {
+ Usage("Only one profile file should be specified.");
+ }
+ if (reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
+ Usage("No reference profile file specified.");
+ }
+
+ if (apk_files_.empty() && apks_fd_.empty()) {
+ Usage("No apk files specified");
+ }
+
+ bool use_fds = profile_files_fd_.size() == 1;
+
+ ProfileCompilationInfo profile;
+ // Do not clear if invalid. The input might be an archive.
+ if (profile.Load(profile_files_[0], /*clear_if_invalid*/ false)) {
+ // Open the dex files to look up classes and methods.
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ OpenApkFilesFromLocations(&dex_files);
+ if (!profile.UpdateProfileKeys(dex_files)) {
+ return false;
+ }
+ return use_fds
+ ? profile.Save(reference_profile_file_fd_)
+ : profile.Save(reference_profile_file_, /*bytes_written*/ nullptr);
+ } else {
+ return false;
+ }
+ }
+
private:
static void ParseFdForCollection(const StringPiece& option,
const char* arg_name,
@@ -1114,6 +1157,7 @@ class ProfMan FINAL {
uint16_t test_profile_class_percentage_;
uint32_t test_profile_seed_;
uint64_t start_ns_;
+ bool copy_and_update_profile_key_;
};
// See ProfileAssistant::ProcessingResult for return codes.