Perform profile file analysis in dex2oat
Dex2oat can accept now multiple profile files to drive a profile based
compilation. --profile-file and --reference-profile-file speficy a pair
of profile files which will be evaluated for significant differences
before starting the compilation. If the difference is insignificant
(according to some internal metric) the compilation is skipped and a
message is logged.
Multiple pairs of --profile-file and --reference-profile-file can be
specified. This effectively enables multi user support since profiles
for different users will be kept separately.
--reference-profile-file can be left out, case in which the decision is
solely based on --profile-file. If both flags are present, then their
repetition should form unique pairs.
If the compilation is performed and --reference-profile-file is given
then its data is merged with the data from the corresponding --profile-
file and saved back to the file.
If no profile flags are given, dex2oat proceeds as before and compiles
the dex files unconditionally.
As part of this change
- merge ProfileCompilationInfo and OfflineProfilingInfo under the same
object. There was no use to keep them separate anymore.
- SaveProfilingInfo now merges the data with what was in
the file before instead of overwriting it.
Bug: 26080105
Change-Id: Ia8c8b55587d468bca5179f78941854285426234d
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 50480d9..c4f68ea 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -63,6 +63,7 @@
#include "gc/space/space-inl.h"
#include "image_writer.h"
#include "interpreter/unstarted_runtime.h"
+#include "jit/offline_profiling_info.h"
#include "leb128.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
@@ -70,6 +71,7 @@
#include "mirror/object_array-inl.h"
#include "oat_writer.h"
#include "os.h"
+#include "profile_assistant.h"
#include "runtime.h"
#include "runtime_options.h"
#include "ScopedLocalRef.h"
@@ -328,6 +330,16 @@
UsageError(" Example: --runtime-arg -Xms256m");
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.");
+ UsageError("");
+ UsageError(" --reference-profile-file=<filename>: specify a reference profile file to use when");
+ UsageError(" compiling. The data in this file will be compared with the data in the");
+ UsageError(" associated --profile-file and the compilation will proceed only if there is");
+ UsageError(" a significant difference (--reference-profile-file is paired with");
+ UsageError(" --profile-file in the natural order). If the compilation was attempted then");
+ UsageError(" --profile-file will be merged into --reference-profile-file. Valid only when");
+ UsageError(" specified together with --profile-file.");
UsageError("");
UsageError(" --print-pass-names: print a list of pass names");
UsageError("");
@@ -767,6 +779,13 @@
}
}
+ if (!profile_files_.empty()) {
+ if (!reference_profile_files_.empty() &&
+ (reference_profile_files_.size() != profile_files_.size())) {
+ Usage("If specified, --reference-profile-file should match the number of --profile-file.");
+ }
+ }
+
if (!parser_options->oat_symbols.empty()) {
oat_unstripped_ = std::move(parser_options->oat_symbols);
}
@@ -1057,8 +1076,10 @@
} else if (option.starts_with("--compiler-backend=")) {
ParseCompilerBackend(option, parser_options.get());
} else if (option.starts_with("--profile-file=")) {
- profile_file_ = option.substr(strlen("--profile-file=")).data();
- VLOG(compiler) << "dex2oat: profile file is " << profile_file_;
+ profile_files_.push_back(option.substr(strlen("--profile-file=")).ToString());
+ } else if (option.starts_with("--reference-profile-file=")) {
+ reference_profile_files_.push_back(
+ option.substr(strlen("--reference-profile-file=")).ToString());
} else if (option == "--no-profile-file") {
// No profile
} else if (option == "--host") {
@@ -1479,9 +1500,8 @@
dump_cfg_append_,
compiler_phases_timings_.get(),
swap_fd_,
- profile_file_,
- &dex_file_oat_filename_map_));
-
+ &dex_file_oat_filename_map_,
+ profile_compilation_info_.get()));
driver_->SetDexFilesForOatFile(dex_files_);
driver_->CompileAll(class_loader, dex_files_, timings_);
}
@@ -1790,6 +1810,26 @@
return is_host_;
}
+ bool UseProfileGuidedCompilation() const {
+ return !profile_files_.empty();
+ }
+
+ bool ProcessProfiles() {
+ DCHECK(UseProfileGuidedCompilation());
+ ProfileCompilationInfo* info = nullptr;
+ if (ProfileAssistant::ProcessProfiles(profile_files_, reference_profile_files_, &info)) {
+ profile_compilation_info_.reset(info);
+ return true;
+ }
+ return false;
+ }
+
+ bool ShouldCompileBasedOnProfiles() const {
+ DCHECK(UseProfileGuidedCompilation());
+ // If we are given profiles, compile only if we have new information.
+ return profile_compilation_info_ != nullptr;
+ }
+
private:
template <typename T>
static std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) {
@@ -2263,7 +2303,9 @@
int swap_fd_;
std::string app_image_file_name_;
int app_image_fd_;
- std::string profile_file_; // Profile file to use
+ std::vector<std::string> profile_files_;
+ std::vector<std::string> reference_profile_files_;
+ std::unique_ptr<ProfileCompilationInfo> profile_compilation_info_;
TimingLogger* timings_;
std::unique_ptr<CumulativeLogger> compiler_phases_timings_;
std::vector<std::vector<const DexFile*>> dex_files_per_oat_file_;
@@ -2380,6 +2422,20 @@
// Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError.
dex2oat.ParseArgs(argc, argv);
+ // Process profile information and assess if we need to do a profile guided compilation.
+ // This operation involves I/O.
+ if (dex2oat.UseProfileGuidedCompilation()) {
+ if (dex2oat.ProcessProfiles()) {
+ if (!dex2oat.ShouldCompileBasedOnProfiles()) {
+ LOG(INFO) << "Skipped compilation because of insignificant profile delta";
+ return EXIT_SUCCESS;
+ }
+ } else {
+ LOG(WARNING) << "Failed to process profile files";
+ return EXIT_FAILURE;
+ }
+ }
+
// Check early that the result of compilation can be written
if (!dex2oat.OpenFile()) {
return EXIT_FAILURE;