summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2023-05-05 12:53:34 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2023-05-09 09:12:15 +0000
commit441e3bf277308722aec934e7984d35309074d1a7 (patch)
treef7c666cb02bea636c312acc1b4962c964b579a4f
parent429b584f59a317803ddb93d237a954c85b66dda4 (diff)
Cleanup logic on madvising vdex/dex files.
- Be consistent between dex in .vdex file and uncompressed dex file in APK - Remove old and duplicated madvise logic for low ram. Test: test.py Bug: 278785544 Bug: 196052575 Bug: 178853586 Change-Id: I0b9cbf3273091cf7cbd8add9966ba21f6ac93d45
-rw-r--r--libdexfile/dex/dex_file_layout.cc51
-rw-r--r--libdexfile/dex/dex_file_layout.h9
-rw-r--r--runtime/class_linker.cc3
-rw-r--r--runtime/oat_file.cc28
-rw-r--r--runtime/oat_file.h3
-rw-r--r--runtime/oat_file_manager.cc42
-rw-r--r--runtime/parsed_options.cc1
-rw-r--r--runtime/runtime.cc13
-rw-r--r--runtime/runtime.h17
9 files changed, 33 insertions, 134 deletions
diff --git a/libdexfile/dex/dex_file_layout.cc b/libdexfile/dex/dex_file_layout.cc
index f15e925446..f4dd2c5f9e 100644
--- a/libdexfile/dex/dex_file_layout.cc
+++ b/libdexfile/dex/dex_file_layout.cc
@@ -16,63 +16,12 @@
#include "dex_file_layout.h"
-
#include "base/bit_utils.h"
#include "base/mman.h"
#include "dex_file.h"
namespace art {
-int DexLayoutSection::MadviseLargestPageAlignedRegion(const uint8_t* begin,
- const uint8_t* end,
- int advice) {
-#ifdef _WIN32
- UNUSED(begin);
- UNUSED(end);
- UNUSED(advice);
- PLOG(WARNING) << "madvise is unsupported on Windows.";
-#else
- DCHECK_LE(begin, end);
- begin = AlignUp(begin, kPageSize);
- end = AlignDown(end, kPageSize);
- if (begin < end) {
- // TODO: remove the direct dependency on madvise here.
- int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice);
- if (result != 0) {
- PLOG(WARNING) << "madvise failed " << result;
- }
- return result;
- }
-#endif
- return 0;
-}
-
-void DexLayoutSection::Subsection::Madvise(const DexFile* dex_file, int advice) const {
- DCHECK(dex_file != nullptr);
- DCHECK_LT(start_offset_, dex_file->Size());
- DCHECK_LE(end_offset_, dex_file->Size());
- MadviseLargestPageAlignedRegion(dex_file->Begin() + start_offset_,
- dex_file->Begin() + end_offset_,
- advice);
-}
-
-void DexLayoutSections::MadviseAtLoad(const DexFile* dex_file) const {
-#ifdef _WIN32
- UNUSED(dex_file);
- PLOG(WARNING) << "madvise is unsupported on Windows.";
-#else
- // The dex file is already defaulted to random access everywhere.
- for (const DexLayoutSection& section : sections_) {
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)].Madvise(
- dex_file,
- MADV_WILLNEED);
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)].Madvise(
- dex_file,
- MADV_WILLNEED);
- }
-#endif
-}
-
std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section) {
for (size_t i = 0; i < static_cast<size_t>(LayoutType::kLayoutTypeCount); ++i) {
const DexLayoutSection::Subsection& part = section.parts_[i];
diff --git a/libdexfile/dex/dex_file_layout.h b/libdexfile/dex/dex_file_layout.h
index e1ae44d31d..5fc37d107a 100644
--- a/libdexfile/dex/dex_file_layout.h
+++ b/libdexfile/dex/dex_file_layout.h
@@ -82,13 +82,8 @@ class DexLayoutSection {
end_offset_ = std::max(end_offset_, end_offset);
}
}
-
- void Madvise(const DexFile* dex_file, int advice) const;
};
- // Madvise the largest page-aligned region contained in [begin, end).
- static int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice);
-
Subsection parts_[static_cast<size_t>(LayoutType::kLayoutTypeCount)];
};
@@ -101,10 +96,6 @@ class DexLayoutSections {
kSectionCount,
};
- // Advise load access about the dex file based on layout. The caller is expected to have already
- // madvised to MADV_RANDOM.
- void MadviseAtLoad(const DexFile* dex_file) const;
-
DexLayoutSection sections_[static_cast<size_t>(SectionType::kSectionCount)];
};
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4ef00615d1..19f79481f5 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1405,9 +1405,6 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
error_msg)) {
return false;
}
- for (const std::unique_ptr<const DexFile>& dex_file : boot_dex_files_) {
- OatDexFile::MadviseDexFileAtLoad(*dex_file);
- }
InitializeObjectVirtualMethodHashes(GetClassRoot<mirror::Object>(this),
image_pointer_size_,
ArrayRef<uint32_t>(object_virtual_method_hashes_));
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index ab26ee963b..5f74584a74 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -2351,34 +2351,6 @@ const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
return nullptr;
}
-// Madvise the dex file based on the state we are moving to.
-void OatDexFile::MadviseDexFileAtLoad(const DexFile& dex_file) {
- Runtime* const runtime = Runtime::Current();
- const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
- // TODO(b/196052575): Revisit low-ram madvise behavior in light of vdex/odex/art madvise hints.
- if (!low_ram) {
- return;
- }
- if (runtime->MAdviseRandomAccess()) {
- // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
- // Other devices have enough page cache to get performance benefits from loading more pages
- // into the page cache.
- DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
- dex_file.Begin() + dex_file.Size(),
- MADV_RANDOM);
- }
- const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
- if (oat_dex_file != nullptr) {
- // Should always be there.
- const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
- if (sections != nullptr) {
- sections->MadviseAtLoad(&dex_file);
- } else {
- DCHECK(oat_dex_file->IsBackedByVdexOnly());
- }
- }
-}
-
OatFile::OatClass::OatClass(const OatFile* oat_file,
ClassStatus status,
OatClassType type,
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index d52723a98e..68adb987c0 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -564,9 +564,6 @@ class OatDexFile final {
const char* descriptor,
size_t hash);
- // Madvise the dex file for load-time usage.
- static void MadviseDexFileAtLoad(const DexFile& dex_file);
-
const TypeLookupTable& GetTypeLookupTable() const {
return lookup_table_;
}
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 25ebaff7d5..63e005dfe1 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -230,9 +230,9 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
// We only want to madvise primary/split dex artifacts as a startup optimization. However,
// as the code_type for those artifacts may not be set until the initial app info registration,
// we conservatively madvise everything until the app info registration is complete.
- const bool should_madvise_vdex_and_odex = !has_registered_app_info ||
- code_type == AppInfo::CodeType::kPrimaryApk ||
- code_type == AppInfo::CodeType::kSplitApk;
+ const bool should_madvise = !has_registered_app_info ||
+ code_type == AppInfo::CodeType::kPrimaryApk ||
+ code_type == AppInfo::CodeType::kSplitApk;
// Proceed with oat file loading.
std::unique_ptr<const OatFile> oat_file(oat_file_assistant->GetBestOatFile().release());
@@ -250,7 +250,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter());
// Load the dex files from the oat file.
bool added_image_space = false;
- if (should_madvise_vdex_and_odex) {
+ if (should_madvise) {
VLOG(oat) << "Madvising oat file: " << oat_file->GetLocation();
size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
Runtime::MadviseFileForRange(madvise_size_limit,
@@ -377,27 +377,25 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
if (dex_files.empty()) {
ScopedTrace failed_to_open_dex_files("FailedToOpenDexFilesFromOat");
error_msgs->push_back("Failed to open dex files from " + odex_location);
- } else {
- // Opened dex files from an oat file, madvise them to their loaded state.
- for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
- OatDexFile::MadviseDexFileAtLoad(*dex_file);
- }
- }
-
- if (oat_file != nullptr) {
- VdexFile* vdex_file = oat_file->GetVdexFile();
- if (should_madvise_vdex_and_odex && vdex_file != nullptr) {
- VLOG(oat) << "Madvising vdex file: " << vdex_file->GetName();
- // Opened vdex file from an oat file, madvise it to its loaded state.
- // TODO(b/196052575): Unify dex and vdex madvise knobs and behavior.
- const size_t madvise_size_limit = Runtime::Current()->GetMadviseWillNeedSizeVdex();
+ } else if (should_madvise) {
+ size_t madvise_size_limit = Runtime::Current()->GetMadviseWillNeedTotalDexSize();
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ // Prefetch the dex file based on vdex size limit (name should
+ // have been dex size limit).
+ VLOG(oat) << "Madvising dex file: " << dex_file->GetLocation();
Runtime::MadviseFileForRange(madvise_size_limit,
- vdex_file->Size(),
- vdex_file->Begin(),
- vdex_file->End(),
- vdex_file->GetName());
+ dex_file->Size(),
+ dex_file->Begin(),
+ dex_file->Begin() + dex_file->Size(),
+ dex_file->GetLocation());
+ if (dex_file->Size() >= madvise_size_limit) {
+ break;
+ }
+ madvise_size_limit -= dex_file->Size();
}
+ }
+ if (oat_file != nullptr) {
VLOG(class_linker) << "Registering " << oat_file->GetLocation();
*out_oat_file = RegisterOatFile(std::move(oat_file));
}
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 6b77ce8569..7df765fe29 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -250,6 +250,7 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize
.WithValueMap({{"false", false}, {"true", true}})
.IntoKey(M::DumpNativeStackOnSigQuit)
.Define("-XX:MadviseRandomAccess:_")
+ .WithHelp("Deprecated option")
.WithType<bool>()
.WithValueMap({{"false", false}, {"true", true}})
.IntoKey(M::MadviseRandomAccess)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1cbc6e245f..69f0fbb4ec 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -298,7 +298,7 @@ Runtime::Runtime()
experimental_flags_(ExperimentalFlags::kNone),
oat_file_manager_(nullptr),
is_low_memory_mode_(false),
- madvise_willneed_vdex_filesize_(0),
+ madvise_willneed_total_dex_size_(0),
madvise_willneed_odex_filesize_(0),
madvise_willneed_art_filesize_(0),
safe_mode_(false),
@@ -1585,8 +1585,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
zygote_max_failed_boots_ = runtime_options.GetOrDefault(Opt::ZygoteMaxFailedBoots);
experimental_flags_ = runtime_options.GetOrDefault(Opt::Experimental);
is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode);
- madvise_random_access_ = runtime_options.GetOrDefault(Opt::MadviseRandomAccess);
- madvise_willneed_vdex_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedVdexFileSize);
+ madvise_willneed_total_dex_size_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedVdexFileSize);
madvise_willneed_odex_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedOdexFileSize);
madvise_willneed_art_filesize_ = runtime_options.GetOrDefault(Opt::MadviseWillNeedArtFileSize);
@@ -3397,6 +3396,8 @@ void Runtime::MadviseFileForRange(size_t madvise_size_limit_bytes,
const uint8_t* map_begin,
const uint8_t* map_end,
const std::string& file_name) {
+ map_begin = AlignDown(map_begin, kPageSize);
+ map_size_bytes = RoundUp(map_size_bytes, kPageSize);
#ifdef ART_TARGET_ANDROID
// Short-circuit the madvise optimization for background processes. This
// avoids IO and memory contention with foreground processes, particularly
@@ -3429,7 +3430,7 @@ void Runtime::MadviseFileForRange(size_t madvise_size_limit_bytes,
// Clamp endOfFile if its past map_end
if (target_pos > map_end) {
- target_pos = map_end;
+ target_pos = map_end;
}
// Madvise the whole file up to target_pos in chunks of
@@ -3447,7 +3448,9 @@ void Runtime::MadviseFileForRange(size_t madvise_size_limit_bytes,
int status = madvise(madvise_addr, madvise_length, MADV_WILLNEED);
// In case of error we stop madvising rest of the file
if (status < 0) {
- LOG(ERROR) << "Failed to madvise file:" << file_name << " for size:" << map_size_bytes;
+ LOG(ERROR) << "Failed to madvise file " << file_name
+ << " for size:" << map_size_bytes
+ << ": " << strerror(errno);
break;
}
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 3da8f0a726..9ec9937f03 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -1004,14 +1004,8 @@ class Runtime {
return deny_art_apex_data_files_;
}
- // Whether or not we use MADV_RANDOM on files that are thought to have random access patterns.
- // This is beneficial for low RAM devices since it reduces page cache thrashing.
- bool MAdviseRandomAccess() const {
- return madvise_random_access_;
- }
-
- size_t GetMadviseWillNeedSizeVdex() const {
- return madvise_willneed_vdex_filesize_;
+ size_t GetMadviseWillNeedTotalDexSize() const {
+ return madvise_willneed_total_dex_size_;
}
size_t GetMadviseWillNeedSizeOdex() const {
@@ -1475,13 +1469,10 @@ class Runtime {
// Whether or not we are on a low RAM device.
bool is_low_memory_mode_;
- // Whether or not we use MADV_RANDOM on files that are thought to have random access patterns.
- // This is beneficial for low RAM devices since it reduces page cache thrashing.
- bool madvise_random_access_;
-
// Limiting size (in bytes) for applying MADV_WILLNEED on vdex files
+ // or uncompressed dex files in APKs.
// A 0 for this will turn off madvising to MADV_WILLNEED
- size_t madvise_willneed_vdex_filesize_;
+ size_t madvise_willneed_total_dex_size_;
// Limiting size (in bytes) for applying MADV_WILLNEED on odex files
// A 0 for this will turn off madvising to MADV_WILLNEED