8153745: Avoid spawning G1ParPreserveCMReferentsTask when there is no work to be done
authorsjohanss
Thu, 14 Apr 2016 08:30:37 +0200
changeset 37494 bf6caf8e99cb
parent 37493 5da80e1490de
child 37496 ffa69cc1dcc0
child 37497 acb4d765e845
child 37500 d21941e2e3fe
8153745: Avoid spawning G1ParPreserveCMReferentsTask when there is no work to be done Reviewed-by: brutisso, jmasa, tschatzl
hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
hotspot/src/share/vm/gc/shared/referenceProcessor.hpp
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Apr 14 08:30:15 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Apr 14 08:30:37 2016 +0200
@@ -4452,7 +4452,6 @@
 }
 
 void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) {
-  double preserve_cm_referents_start = os::elapsedTime();
   // Any reference objects, in the collection set, that were 'discovered'
   // by the CM ref processor should have already been copied (either by
   // applying the external root copy closure to the discovered lists, or
@@ -4473,16 +4472,24 @@
   // objects discovered by the STW ref processor in case one of these
   // referents points to another object which is also referenced by an
   // object discovered by the STW ref processor.
-
-  uint no_of_gc_workers = workers()->active_workers();
-
-  G1ParPreserveCMReferentsTask keep_cm_referents(this,
-                                                 per_thread_states,
-                                                 no_of_gc_workers,
-                                                 _task_queues);
-  workers()->run_task(&keep_cm_referents);
-
-  g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0);
+  double preserve_cm_referents_time = 0.0;
+
+  // To avoid spawning task when there is no work to do, check that
+  // a concurrent cycle is active and that some references have been
+  // discovered.
+  if (concurrent_mark()->cmThread()->during_cycle() &&
+      ref_processor_cm()->has_discovered_references()) {
+    double preserve_cm_referents_start = os::elapsedTime();
+    uint no_of_gc_workers = workers()->active_workers();
+    G1ParPreserveCMReferentsTask keep_cm_referents(this,
+                                                   per_thread_states,
+                                                   no_of_gc_workers,
+                                                   _task_queues);
+    workers()->run_task(&keep_cm_referents);
+    preserve_cm_referents_time = os::elapsedTime() - preserve_cm_referents_start;
+  }
+
+  g1_policy()->phase_times()->record_preserve_cm_referents_time_ms(preserve_cm_referents_time * 1000.0);
 }
 
 // Weak Reference processing during an evacuation pause (part 1).
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Thu Apr 14 08:30:15 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Thu Apr 14 08:30:37 2016 +0200
@@ -1090,6 +1090,15 @@
   return true;
 }
 
+bool ReferenceProcessor::has_discovered_references() {
+  for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
+    if (!_discovered_refs[i].is_empty()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // Preclean the discovered references by removing those
 // whose referents are alive, and by marking from those that
 // are not active. These lists can be handled here
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Thu Apr 14 08:30:15 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp	Thu Apr 14 08:30:37 2016 +0200
@@ -412,6 +412,9 @@
   // Discover a Reference object, using appropriate discovery criteria
   bool discover_reference(oop obj, ReferenceType rt);
 
+  // Has discovered references that need handling
+  bool has_discovered_references();
+
   // Process references found during GC (called by the garbage collector)
   ReferenceProcessorStats
   process_discovered_references(BoolObjectClosure*           is_alive,