diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -3115,10 +3115,22 @@
 
 void G1ParEvacuateFollowersClosure::do_void() {
   G1ParScanThreadState* const pss = par_scan_state();
+  double start_sec = os::elapsedTime();
+  log_debug(gc, ergo)("Initial queue size of worker %u is %u", pss->worker_id(), pss->queue_size()),
   pss->trim_queue();
+  log_debug(gc, ergo)("Trim queue time of worker %u is %f ms, pushed obj with partial array is %u, max length is %d", pss->worker_id(), (os::elapsedTime() - start_sec) * 1000, pss->get_pushed_obj_with_paritial_array(), pss->get_max_length());
+
+  pss->reset_max_length();
+  start_sec = os::elapsedTime();
+  uint i = 0;
   do {
-    pss->steal_and_trim_queue(queues());
+    uint stealed_task = pss->steal_and_trim_queue(queues());
+    i++;
+    log_debug(gc, ergo)("worker %u %u: Stealed and processed %u tasks, max length is %d", pss->worker_id(), i, stealed_task, pss->get_max_length());
+    pss->reset_max_length();
   } while (!offer_termination());
+  log_debug(gc, ergo)("Steal and trim time of worker %u is %f ms, pushed obj with partial array is %u", pss->worker_id(), (os::elapsedTime() - start_sec) * 1000, pss->get_pushed_obj_with_paritial_array());
+  pss->reset_pushed_obj_with_paritial_array();
 }
 
 class G1ParTask : public AbstractGangTask {
diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
@@ -52,7 +52,9 @@
     _stack_trim_upper_threshold(GCDrainStackTargetSize * 2 + 1),
     _stack_trim_lower_threshold(GCDrainStackTargetSize),
     _trim_ticks(),
-    _old_gen_is_full(false)
+    _old_gen_is_full(false),
+    _pushed_obj_with_partial_array(0),
+    _max_length(0)
 {
   // we allocate G1YoungSurvRateNumRegions plus one entries, since
   // we "sacrifice" entry 0 to keep track of surviving bytes for
diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
@@ -53,12 +53,14 @@
 
   AgeTable          _age_table;
   InCSetState       _dest[InCSetState::Num];
-  // Local tenuring threshold.
+  // Local tenuring thresholdj
   uint              _tenuring_threshold;
   G1ScanEvacuatedObjClosure  _scanner;
 
   int  _hash_seed;
   uint _worker_id;
+  uint _pushed_obj_with_partial_array;
+  int _max_length;
 
   // Upper and lower threshold to start and end work queue draining.
   uint const _stack_trim_upper_threshold;
@@ -93,6 +95,11 @@
   virtual ~G1ParScanThreadState();
 
   void set_ref_discoverer(ReferenceDiscoverer* rd) { _scanner.set_ref_discoverer(rd); }
+  uint queue_size() const { return _refs->size(); }
+  uint get_pushed_obj_with_paritial_array() const { return _pushed_obj_with_partial_array; }
+  void reset_pushed_obj_with_paritial_array() { _pushed_obj_with_partial_array = 0; }
+  int get_max_length() const { return _max_length; }
+  void reset_max_length() { _max_length = 0; }
 
 #ifdef ASSERT
   bool queue_is_empty() const { return _refs->is_empty(); }
@@ -204,7 +211,7 @@
   Tickspan trim_ticks() const;
   void reset_trim_ticks();
 
-  inline void steal_and_trim_queue(RefToScanQueueSet *task_queues);
+  inline uint steal_and_trim_queue(RefToScanQueueSet *task_queues);
 
   // An attempt to evacuate "obj" has failed; take necessary steps.
   oop handle_evacuation_failure_par(oop obj, markOop m);
diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp
@@ -76,6 +76,9 @@
   objArrayOop from_obj_array = objArrayOop(from_obj);
   // The from-space object contains the real length.
   int length                 = from_obj_array->length();
+  if (length > _max_length) {
+    _max_length = length;
+  }
 
   assert(from_obj->is_forwarded(), "must be forwarded");
   oop to_obj                 = from_obj->forwardee();
@@ -98,6 +101,7 @@
     // worker has run out of things to do and can steal it.
     oop* from_obj_p = set_partial_array_mask(from_obj);
     push_on_queue(from_obj_p);
+    _pushed_obj_with_partial_array++;
   } else {
     assert(length == end, "sanity");
     // We'll process the final range for this object. Restore the length
@@ -138,8 +142,9 @@
   }
 }
 
-void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) {
+uint G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) {
   StarTask stolen_task;
+  uint stealed_task = 0;
   while (task_queues->steal(_worker_id, &_hash_seed, stolen_task)) {
     assert(verify_task(stolen_task), "sanity");
     dispatch_reference(stolen_task);
@@ -148,7 +153,9 @@
     // available new entries on the queues. So we have to make sure
     // we drain the queues as necessary.
     trim_queue();
+    stealed_task++;
   }
+  return stealed_task;
 }

diff --git a/src/hotspot/share/gc/shared/taskqueue.inline.hpp b/src/hotspot/share/gc/shared/taskqueue.inline.hpp
--- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp
+++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp
@@ -237,8 +237,22 @@
     // Sample both and try the larger.
     uint sz1 = _queues[k1]->size();
     uint sz2 = _queues[k2]->size();
-    if (sz2 > sz1) return _queues[k2]->pop_global(t);
-    else return _queues[k1]->pop_global(t);
+    if (sz2 > sz1) {
+      bool result = _queues[k2]->pop_global(t);
+      if (result) {
+        log_debug(gc, ergo)("worker %u stealed from queue %u, its size was %u", queue_num, k2, sz2);
+      }
+      return result;
+    } else {
+      bool result = _queues[k1]->pop_global(t);
+      if (result) {
+        log_debug(gc, ergo)("worker %u stealed from queue %u, its size was %u", queue_num, k1, sz1);
+      }
+      return result;
+    }
   } else if (_n == 2) {
     // Just try the other one.
     uint k = (queue_num + 1) % 2;
