OSDN Git Service

Add soft reference pre processing.
authorMathieu Chartier <mathieuc@google.com>
Thu, 20 Mar 2014 00:08:17 +0000 (17:08 -0700)
committerMathieu Chartier <mathieuc@google.com>
Thu, 20 Mar 2014 16:17:02 +0000 (09:17 -0700)
Soft reference pre-processing does soft reference preservation with
mutators running. After this is done, it does another pass with
mutators paused in the ProcessReference code. This helps lower pauses
since most preserved soft references have their referents recursive
marked outside the pause.

Changed ergonomics to have non sticky collectors always clear the
soft references.

Maps pauses ~10ms -> ~3ms on Nexus 4.

Bug: 13421927

Change-Id: I1370f7bb6934034869aa5afca0c377876267aa8e

runtime/gc/collector/mark_sweep.cc
runtime/gc/collector/mark_sweep.h
runtime/gc/heap.cc
runtime/gc/heap.h

index fe5a75f..8372734 100644 (file)
@@ -145,6 +145,12 @@ void MarkSweep::ProcessReferences(Thread* self) {
                                &MarkObjectCallback, &ProcessMarkStackPausedCallback, this);
 }
 
+void MarkSweep::PreProcessReferences(Thread* self) {
+  timings_.NewSplit("PreProcessReferences");
+  GetHeap()->ProcessSoftReferences(timings_, clear_soft_references_, &IsMarkedCallback,
+                                   &MarkObjectCallback, &ProcessMarkStackPausedCallback, this);
+}
+
 bool MarkSweep::HandleDirtyObjectsPhase() {
   TimingLogger::ScopedSplit split("(Paused)HandleDirtyObjectsPhase", &timings_);
   Thread* self = Thread::Current();
@@ -255,6 +261,11 @@ void MarkSweep::MarkingPhase() {
   MarkReachableObjects();
   // Pre-clean dirtied cards to reduce pauses.
   PreCleanCards();
+  if (IsConcurrent()) {
+    // No reason to do this for non-concurrent GC since pre processing soft references only helps
+    // pauses.
+    PreProcessReferences(self);
+  }
 }
 
 void MarkSweep::UpdateAndMarkModUnion() {
index df19f88..b117b20 100644 (file)
@@ -126,6 +126,10 @@ class MarkSweep : public GarbageCollector {
   void ProcessReferences(Thread* self)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void PreProcessReferences(Thread* self)
+      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Update and mark references from immune spaces. Virtual as overridden by StickyMarkSweep.
   virtual void UpdateAndMarkModUnion()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
index e8ee62f..a763e37 100644 (file)
@@ -751,22 +751,31 @@ mirror::Object* Heap::PreserveSoftReferenceCallback(mirror::Object* obj, void* a
   return args->mark_callback_(obj, args->arg_);
 }
 
-// Process reference class instances and schedule finalizations.
-void Heap::ProcessReferences(TimingLogger& timings, bool clear_soft,
-                             IsMarkedCallback* is_marked_callback,
-                             MarkObjectCallback* mark_object_callback,
-                             ProcessMarkStackCallback* process_mark_stack_callback, void* arg) {
-  // Unless we are in the zygote or required to clear soft references with white references,
-  // preserve some white referents.
-  if (!clear_soft && !Runtime::Current()->IsZygote()) {
+void Heap::ProcessSoftReferences(TimingLogger& timings, bool clear_soft,
+                                 IsMarkedCallback* is_marked_callback,
+                                 MarkObjectCallback* mark_object_callback,
+                                 ProcessMarkStackCallback* process_mark_stack_callback, void* arg) {
+  // Unless required to clear soft references with white references, preserve some white referents.
+  if (!clear_soft) {
+    // Don't clear for sticky GC.
     SoftReferenceArgs soft_reference_args;
     soft_reference_args.is_marked_callback_ = is_marked_callback;
     soft_reference_args.mark_callback_ = mark_object_callback;
     soft_reference_args.arg_ = arg;
+    // References with a marked referent are removed from the list.
     soft_reference_queue_.PreserveSomeSoftReferences(&PreserveSoftReferenceCallback,
                                                      &soft_reference_args);
     process_mark_stack_callback(arg);
   }
+}
+
+// Process reference class instances and schedule finalizations.
+void Heap::ProcessReferences(TimingLogger& timings, bool clear_soft,
+                             IsMarkedCallback* is_marked_callback,
+                             MarkObjectCallback* mark_object_callback,
+                             ProcessMarkStackCallback* process_mark_stack_callback, void* arg) {
+  ProcessSoftReferences(timings, clear_soft, is_marked_callback, mark_object_callback,
+                        process_mark_stack_callback, arg);
   timings.StartSplit("(Paused)ProcessReferences");
   // Clear all remaining soft and weak references with white referents.
   soft_reference_queue_.ClearWhiteReferences(cleared_references_, is_marked_callback, arg);
@@ -1813,7 +1822,10 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, GcCaus
       << "Could not find garbage collector with concurrent=" << concurrent_gc_
       << " and type=" << gc_type;
   ATRACE_BEGIN(StringPrintf("%s %s GC", PrettyCause(gc_cause), collector->GetName()).c_str());
-  collector->Run(gc_cause, clear_soft_references);
+  if (!clear_soft_references) {
+    clear_soft_references = gc_type != collector::kGcTypeSticky;  // TODO: GSS?
+  }
+  collector->Run(gc_cause, clear_soft_references || Runtime::Current()->IsZygote());
   total_objects_freed_ever_ += collector->GetFreedObjects();
   total_bytes_freed_ever_ += collector->GetFreedBytes();
   RequestHeapTrim();
index de20a4e..eb53ba9 100644 (file)
@@ -314,6 +314,12 @@ class Heap {
   }
 
   static mirror::Object* PreserveSoftReferenceCallback(mirror::Object* obj, void* arg);
+  void ProcessSoftReferences(TimingLogger& timings, bool clear_soft,
+                             IsMarkedCallback* is_marked_callback,
+                             MarkObjectCallback* mark_object_callback,
+                             ProcessMarkStackCallback* process_mark_stack_callback, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
   void ProcessReferences(TimingLogger& timings, bool clear_soft,
                          IsMarkedCallback* is_marked_callback,
                          MarkObjectCallback* mark_object_callback,