RFR: Generational/LRU partial heuristics take two...

Aleksey Shipilev shade at redhat.com
Fri Jul 21 08:12:53 UTC 2017


On 07/20/2017 10:38 PM, Christine Flood wrote:
> http://cr.openjdk.java.net/~chf/GenerationalPartialGC/webrev.00/

=== General comments:

 *) Add new heuristics to the tests. Grep hotspot/test/gc for
"ShenandoahGCHeuristics=partial", and add lines with lru/generational there, and
then try to pass hotspot_gc_shenandoah with it

===  Major issues:

*) Catastrophic underflow opportunity here (size_t is unsigned) in
PartialHeuristics:

  815   bool result = (used - previous_used) * 100 / capacity ...

*) PartialHeuristics destructor leaks memory, should pass from_idxs!

  794     FREE_C_HEAP_ARRAY(size_t, ShenandoahPartialInboundThreshold);

*) LRUPartialHeuristics, missing { on this line, making the whole block
nonsensical! See how indenting does not match, pointing at trouble.

  1006                                  ShenandoahPartialInboundThreshold))

*) Why timestamps are set in  ShenandoahHeapRegionSet::next()? The comments for
timestamps say they are set "as regions are discarded". But SHRS::next is just
the iteration that can be used anywhere. This is calling for trouble.


=== Stylistic:

*) ShenandoahHeuristics, stray whitespace at the end:

 205   virtual void choose_collection_set(ShenandoahCollectionSet*
collection_set, bool minor = false );

*) ShenandoahHeuristics, don't need this:

 272     ShenandoahHeap* heap = ShenandoahHeap::heap();

*) ShenandoahHeuristics, predicate order in the same method:

   if (!hr->is_humongous() && !hr->is_pinned() && !hr->is_empty() &&
        hr->has_live() && !collection_set->is_in(hr)) {

PartialHeuristics:

*) Can be private:

 781   size_t* from_idxs;

*) Too long log_info lines, plus missing punctuation in messaging. Also, braces.
Do e.g.:

  log_info(gc,ergo)("Skip partial GC. Capacity = " SIZE_FORMAT
         ", used = " SIZE_FORMAT ", previous GC used = " SIZE_FORMAT
         ", threshold = " SIZE_FORMAT,
          capacity, used, previous_used, ShenandoahAllocationThreshold);

GenerationalPartialHeuristics:

*) Braces:

  886     for (size_t i = 0; i < active; i++)
  887       sorted_regions.add_region(regions->get(i));

*) Stray newlines:

  893
  894

*) "\n" is not needed. Should have (gc,ergo) tag. log_info(gc,ergo) format
should match the one from parent PartialHeuristics.

  917     log_info(gc)("arbitrary = "SIZE_FORMAT" active = "SIZE_FORMAT" ...

*) Heap is available in local variable at this point:

  933     size_t threshold = ShenandoahHeap::heap()->regions()->active_regions()

*) It is saner to multiply everything first, and then divide, to improve accuracy?

  933   size_t threshold = ShenandoahHeap::heap()->regions()->active_regions() *
  934       percentage_young / 100 *
  935       ShenandoahHeapRegion::region_size_bytes();

*) Whitespace:

  949   bool can_do_partial_gc() { return true;}


LRUPartialHeuristics:

*) This is unused:

  971     outputStream *out = Log(gc)::info_stream();

*) Stray newlines:

  980
  981

*) log_info should have (gc,ergo) tag. Also, what is "arbitrary"? Needs short
descriptive name. "\n" is not needed. log_info(gc,ergo) format should match the
one from parent PartialHeuristics.

 1016       log_info(gc)("arbitrary = "SIZE_FORMAT" ...)

*) Heap is available in local variable at this point:

 1031   size_t threshold = ShenandoahHeap::heap()->regions()->active_regions() *
 1035     size_t minimum = ShenandoahHeap::heap()->regions()->active_regions() *


ShenandoahCollectorPolicy:

*) I guess we can say "false" on behalf of major heuristics here?

   bool ShenandoahCollectorPolicy::can_do_partial_gc() {
     if (_minor_heuristics != NULL)
       return _minor_heuristics->can_do_partial_gc();
     }
     return false; // no minor, no partial gc
   }

*) Whitespace:

  264   ShenandoahHeuristics* heuristics() { return _heuristics;}


ShenandoahConcurrentThread:

*) Why this check here?

   60       if (! heap->need_update_refs())
   61         service_partial_cycle();


ShenandoahConnectionMatrix:

*) Should mention the length for format here, "%8s"?:

   65   st->print_cr("%8s, %10s, %10s, %10s, %8s, %8s, %s, %s",
   66                "Region", "Live", "Used", "Garbage",
   67                "TS_Start", "TS_End", "Refcnt", "Referenced by");
   68

*) Should match the format length for the header, "%8.4f", not "%4.4f"?

   82         st->print("%8u, "SIZE_FORMAT_W(10)", "SIZE_FORMAT_W(10)",
"SIZE_FORMAT_W(10)", %4.4F, %4.4F, %8u, {",

ShenandoahHeap:

*) Excess log_info(gc):

 1976   log_info(gc)("Doing Partial Collection");

*) Whitespace, and also please indent them:

  double timestamp_at_last_gc_end()   const { return _timestamp_...; }
  double timestamp_at_last_gc_start() const { return _timestamp_...; }
  size_t used_at_last_gc()            const { return _used_at_last_gc; }

ShenandoahHeapRegion:

*) Need to set format length:

  148   st->print("|FTS %lf",  first_timestamp());
  149   st->print("|LTS %lf",  last_timestamp());

*) Stray newline:

  284

*) Whitespace and indents:

  185   double first_timestamp() const { return _first_timestamp;}
  186   double last_timestamp() const { return _last_timestamp;}
  187   void   set_first_timestamp() {_first_timestamp = os::elapsedTime();}
  188   void   set_last_timestamp() { _last_timestamp = os::elapsedTime();}


Partial GC:

*) Whitespace difference marks these lines as changed:

   49   void do_oop_work(T* p) {_partial_gc->process_oop<T, false> ...

  244   log_info(gc,ergo)("Got "SIZE_FORMAT" collection set regions, ...

*) Stray whitespace differences:

   93
   95

*) Unused:

  215   outputStream *out = Log(gc)::info_stream();

*) Use _heap->shenandoahPolicy() instead:

  212   ShenandoahCollectorPolicy* policy = (ShenandoahCollectorPolicy*)
_heap->collector_policy();

*) Not sure why DPT::update_pointers and task_queues->clear() are now outside
the block, around L300-305? At least indenting is not right.

Thanks,
-Aleksey



More information about the shenandoah-dev mailing list