From b3ac45b55a09741a951b3c93769d708970d23250 Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Fri, 9 Sep 2016 14:02:25 +0300 Subject: [PATCH] Reduce number of physical pages used for DexCache's arrays This commit reduces the amount of physical pages allocated for the .bss section of an application's oat file. Many of elements in the application's DexCache arrays are empty. But during coping content of the DexCaches arrays from the app's art file into the .bss section all pages become dirty. The commit fixes that by copying non null elements only. So pages in the .bss section that contains zeroes remains untouched. This approach allows to save 209Kb of memory after one minute of GMaps use. This number is the difference between the size of .bss section and the Rss value from the /proc//smaps file. Test: run test-art-host Change-Id: I3d7bed0805b95b5f344303581274ca8e8e69940e --- runtime/class_linker.cc | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 439849bd3..4e077c002 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1239,6 +1239,20 @@ class VerifyDeclaringClassVisitor : public ArtMethodVisitor { gc::accounting::HeapBitmap* const live_bitmap_; }; +// Copies data from one array to another array at the same position +// if pred returns false. If there is a page of continuous data in +// the src array for which pred consistently returns true then +// corresponding page in the dst array will not be touched. +// This should reduce number of allocated physical pages. +template +static void CopyNonNull(const T* src, size_t count, T* dst, const NullPred& pred) { + for (size_t i = 0; i < count; ++i) { + if (!pred(src[i])) { + dst[i] = src[i]; + } + } +} + bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( gc::space::ImageSpace* space, Handle class_loader, @@ -1330,7 +1344,12 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( for (size_t j = 0; kIsDebugBuild && j < num_types; ++j) { DCHECK(types[j].IsNull()); } - std::copy_n(image_resolved_types, num_types, types); + CopyNonNull(image_resolved_types, + num_types, + types, + [](const GcRoot& elem) { + return elem.IsNull(); + }); dex_cache->SetResolvedTypes(types); } if (num_methods != 0u) { @@ -1340,7 +1359,12 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( for (size_t j = 0; kIsDebugBuild && j < num_methods; ++j) { DCHECK(methods[j] == nullptr); } - std::copy_n(image_resolved_methods, num_methods, methods); + CopyNonNull(image_resolved_methods, + num_methods, + methods, + [] (const ArtMethod* method) { + return method == nullptr; + }); dex_cache->SetResolvedMethods(methods); } if (num_fields != 0u) { @@ -1349,7 +1373,12 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches( for (size_t j = 0; kIsDebugBuild && j < num_fields; ++j) { DCHECK(fields[j] == nullptr); } - std::copy_n(dex_cache->GetResolvedFields(), num_fields, fields); + CopyNonNull(dex_cache->GetResolvedFields(), + num_fields, + fields, + [] (const ArtField* field) { + return field == nullptr; + }); dex_cache->SetResolvedFields(fields); } if (num_method_types != 0u) { -- 2.11.0