diff options
author | 2023-05-05 12:53:34 +0100 | |
---|---|---|
committer | 2023-05-09 09:12:15 +0000 | |
commit | 441e3bf277308722aec934e7984d35309074d1a7 (patch) | |
tree | f7c666cb02bea636c312acc1b4962c964b579a4f | |
parent | 429b584f59a317803ddb93d237a954c85b66dda4 (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.cc | 51 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_layout.h | 9 | ||||
-rw-r--r-- | runtime/class_linker.cc | 3 | ||||
-rw-r--r-- | runtime/oat_file.cc | 28 | ||||
-rw-r--r-- | runtime/oat_file.h | 3 | ||||
-rw-r--r-- | runtime/oat_file_manager.cc | 42 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 1 | ||||
-rw-r--r-- | runtime/runtime.cc | 13 | ||||
-rw-r--r-- | runtime/runtime.h | 17 |
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 |