RFR (M): 8137082: Factor out G1 prediction code from G1CollectorPolicy and clean up

Thomas Schatzl thomas.schatzl at oracle.com
Wed Oct 14 15:44:33 UTC 2015


Hi Kim,

  thanks for the review.

On Tue, 2015-10-13 at 18:57 -0400, Kim Barrett wrote:
> On Oct 13, 2015, at 8:26 AM, Thomas Schatzl <thomas.schatzl at oracle.com> wrote:
> > 
> > http://cr.openjdk.java.net/~tschatzl/8137082/webrev.2/ (full)
> > http://cr.openjdk.java.net/~tschatzl/8137082/webrev.0_to_2/ (diff) 
> 
> ------------------------------------------------------------------------------
> 
> I'd prefer that significant numbers of formatting changes were done
> separately from other kinds of changes. For example, I'd rather have
> the signature reformattings in src/share/vm/gc/g1/survRateGroup.cpp
> done as a separate change, to make that easier to review and to avoid
> cluttering functional / refactoring changes with unrelated stuff.

They did not feel like a significant overhead to me, but okay, I will
create a new CR/webrev (JDK-8139583) for them.

> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/g1Predictions.hpp 
>   42   double stddev_estimate_for_small_sample_sets(TruncatedSeq const* seq) const {
>   43     int const samples = seq->num();
>   44     if (samples > 4) {
>   45       return 0.0;
>   46     } else {
>   47       return seq->davg() * (5 - samples) / 2.0;
>   48     }
>   49   }
> 
>   56   double get_new_prediction(TruncatedSeq const* seq) const {
>   57     return MAX2(seq->davg() + _sigma * seq->dsd(),
>   58                 seq->davg() + _sigma * stddev_estimate_for_small_sample_sets(seq));
>   59   }
> 
> I think a negative _sigma would produce unexpected results.  I suspect
> it's not supposed to ever be negative though.  If so, an assert in the
> constructor would help.

Added. Note that the confidence factor passed to the constructor
(G1ConfidencePercent) is always positive.

> I think a negative seq->davg() would produce unexpected results when
> the sample size is small, since the estimated stddev would be
> negative.  I don't know of any reason why the entries in seq couldn't
> have negative values, possibly leading to a negative davg.  I'm not
> sure what should be done in that situation.

We would get negative predictions, which may confuse the estimations.
This would be a bug in the sampling then.

I think it would be more appropriate to do this checking when adding the
values to the sequences (like adding a TimeSequence or such that only
allows adding positive samples).

> And I had the same question as Sangheon about seq possibly being
> empty.  I think that's a shouldn't happen, since there would be
> nothing from which to produce davg either.  But perhaps an assert is
> called for.

davg will be 0.0 as per default value of the sequence member, which
makes the entire term zero.

I temporarily added the assert, but as I suspected there is code that
(correctly) expects that the return value for this case is zero. It is
a non-trivial effort to fix this existing issue, so I created a new CR
(JDK-8139594).

> Ignoring those issues for the moment, I think it would be clearer as
> something like
> 
>   double stddev_estimate(TruncatedSeq const* seq) const {
>     double estimate = seq->dsd();
>     int const samples = seq->num();
>     // Estimate for small sample sets.
>     if (samples < 5) {
>       estimate = MAX2(estimate, seq->davg() * (5 - samples) / 2.0);
>     }
>     return estimate;
>   }
> 
>   double get_new_predication(TruncatedSeq const* seq) const {
>     return seq->davg() + _sigma * stddev_estimate(seq);
>   }

Done.

> 
> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/g1Predictions.hpp 
> src/share/vm/gc/g1/g1Predictions.cpp 
>  61   static void test();
> 
> Declaration and definition should be NOT_PRODUCT-only.
> 

Done

> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/g1CollectorPolicy.hpp
>  168   double get_new_prediction(TruncatedSeq* const seq) const;
> 
> Parameter should be "TruncatedSeq const*".

Done

> 
> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/g1CollectorPolicy.hpp
>  214   enum PredictionConstants {
>  215     TruncatedSeqLength = 10,
>  216     NumPrevPausesForHeuristics = 10
>  217   };
> 
> Pre-existing stylistic issue - feel free to ignore.
> 
> I don't think enums like this serve any useful purpose. The values are
> not actually related in any interesting semantic way; as evidence,
> note that the enum tag is never used. Also, the types of the
> enumerators are limited and determined automatically by the language,
> and in this case are int, even though an unsigned type is likely more
> appropriate for these values that are used as sizes or counts. Of
> course, in this case the place where these constants are used is also
> of type int (and with a similarly non-useful enum), even though
> negative values are inappropriate there too.
> 
> I would use static constants of an appropriate type instead of an enum
> here, e.g. something like
> 
>   static const unsigned TruncatedSeqLength = 10;
> 
> But such a simple change may get one into a warnings mess over mixed
> signed / unsigned operations that would be far out of scope for the
> change under review.

Since this is a common pattern in the existing code, I will keep it as
is, as a future cleanup.

I do agree with the rest of your comments.

> 
> ------------------------------------------------------------------------------  
> src/share/vm/gc/g1/g1CollectorPolicy.cpp 
>  468   if ((2.0 /* magic */ * _predictor.sigma()) * (double) bytes_to_copy > (double) free_bytes) {
> 
> 1309   return (double) pending_cards * predict_cost_per_card_ms() + predict_scan_hcc_ms();
> 
> 1325   return (size_t) ((double) rs_length * predict_young_cards_per_entry_ratio());
> 1329   return (size_t)((double) rs_length * predict_mixed_cards_per_entry_ratio());
> ... and a bunch more following ...
> 
> Pre-existing stylistic issue - feel free to ignore.
> 
> I find the explicit casts (esp. to double) to be unnecessary clutter.

Done.

> 
> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/g1CollectorPolicy.cpp 
> 1388   if (seq->num() == 0) {
> 1389     gclog_or_tty->print("BARF! age is %d", age);
> 1390   }
> 1391   guarantee(seq->num() > 0, "invariant" );
> 
> Pre-existing.
> 
> Remove the conditional logging and replace the guarantee's error message
> with the previously logged message.  (Though maybe remove “BARF!” :-)

Done.

> ------------------------------------------------------------------------------
> src/share/vm/gc/g1/survRateGroup.cpp
> src/share/vm/gc/g1/survRateGroup.hpp
> 
> The policy object in SurvRateGroup::_g1p is only used to obtain the
> predictor.  Perhaps _g1p should be changed to be a reference to the
> predictor instead? 
> 
> ------------------------------------------------------------------------------

Done.

New webrev at

http://cr.openjdk.java.net/~tschatzl/8137082/webrev.3/ (full)
http://cr.openjdk.java.net/~tschatzl/8137082/webrev.2_to_3/ (diff) 

Thanks,
  Thomas





More information about the hotspot-gc-dev mailing list