OSDN Git Service

Reduce number of physical pages used for DexCache's arrays
authorArtem Udovichenko <artem.u@samsung.com>
Fri, 9 Sep 2016 11:02:25 +0000 (14:02 +0300)
committerArtem Udovichenko <artem.u@samsung.com>
Tue, 25 Oct 2016 15:34:12 +0000 (18:34 +0300)
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/<pid>/smaps file.

Test: run test-art-host

Change-Id: I3d7bed0805b95b5f344303581274ca8e8e69940e

runtime/class_linker.cc

index 439849b..4e077c0 100644 (file)
@@ -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 <class T, class NullPred>
+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<mirror::ClassLoader> 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<mirror::Class>& 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) {