ART: Add very-large threshold to dex2oat
Add a variable threshold to dex2oat. If the total dex file size for
an app reaches this threshold, dex2oat will punt all compilation and
compile the app with verify-at-runtime. This ensures smaller compile
time and memory thrashing, while still extracting the dex files and
thus helping with dirty memory later.
Added tests.
Bug: 29557002
Bug: 29790079
Test: m test-art-host-gtest-dex2oat_test
Change-Id: I78870e4a80ccaafcbbe56839e61ced0acd2ca05e
(cherry picked from commit 338a1d206c16427cf61bd42171fa0c8b9cea8165)
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 437aba7..c133980 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -22,6 +22,7 @@
#include <fstream>
#include <iostream>
+#include <limits>
#include <sstream>
#include <string>
#include <unordered_set>
@@ -364,6 +365,10 @@
UsageError(" Example: --swap-dex-count-threshold=10");
UsageError(" Default: %zu", kDefaultMinDexFilesForSwap);
UsageError("");
+ UsageError(" --very-large-app-threshold=<size>: specifies the minimum total dex file size in");
+ UsageError(" bytes to consider the input \"very large\" and punt on the compilation.");
+ UsageError(" Example: --very-large-app-threshold=100000000");
+ UsageError("");
UsageError(" --app-image-fd=<file-descriptor>: specify output file descriptor for app image.");
UsageError(" Example: --app-image-fd=10");
UsageError("");
@@ -1136,6 +1141,11 @@
"--swap-dex-count-threshold",
&min_dex_files_for_swap_,
Usage);
+ } else if (option.starts_with("--very-large-app-threshold=")) {
+ ParseUintOption(option,
+ "--very-large-app-threshold",
+ &very_large_threshold_,
+ Usage);
} else if (option.starts_with("--app-image-file=")) {
app_image_file_name_ = option.substr(strlen("--app-image-file=")).data();
} else if (option.starts_with("--app-image-fd=")) {
@@ -1418,6 +1428,19 @@
}
// Note that dex2oat won't close the swap_fd_. The compiler driver's swap space will do that.
+ // If we need to downgrade the compiler-filter for size reasons, do that check now.
+ if (!IsBootImage() && IsVeryLarge(dex_files_)) {
+ if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kVerifyAtRuntime,
+ compiler_options_->GetCompilerFilter())) {
+ LOG(INFO) << "Very large app, downgrading to verify-at-runtime.";
+ // Note: this change won't be reflected in the key-value store, as that had to be
+ // finalized before loading the dex files. This setup is currently required
+ // to get the size from the DexFile objects.
+ // TODO: refactor. b/29790079
+ compiler_options_->SetCompilerFilter(CompilerFilter::kVerifyAtRuntime);
+ }
+ }
+
if (IsBootImage()) {
// For boot image, pass opened dex files to the Runtime::Create().
// Note: Runtime acquires ownership of these dex files.
@@ -1913,6 +1936,14 @@
return dex_files_size >= min_dex_file_cumulative_size_for_swap_;
}
+ bool IsVeryLarge(std::vector<const DexFile*>& dex_files) {
+ size_t dex_files_size = 0;
+ for (const auto* dex_file : dex_files) {
+ dex_files_size += dex_file->GetHeader().file_size_;
+ }
+ return dex_files_size >= very_large_threshold_;
+ }
+
template <typename T>
static std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) {
std::vector<T*> result;
@@ -2504,6 +2535,7 @@
int swap_fd_;
size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
size_t min_dex_file_cumulative_size_for_swap_ = kDefaultMinDexFileCumulativeSizeForSwap;
+ size_t very_large_threshold_ = std::numeric_limits<size_t>::max();
std::string app_image_file_name_;
int app_image_fd_;
std::string profile_file_;