RFR (M): 8136681: Factor out IHOP calculation from G1CollectorPolicy

Mikael Gerdin mikael.gerdin at oracle.com
Fri Nov 13 15:08:03 UTC 2015

Hi Thomas,

On 2015-11-05 10:42, Thomas Schatzl wrote:
> Hi all,
>    can I have reviews for this preparatory change for adaptive IHOP
> sizing, that factors out the IHOP calculation from G1Collectorpolicy
> into separate classes?
> So instead of having this single line at G1CollectorPolicy:944
>   944   size_t marking_initiating_used_threshold =
>   945     (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent;
> [...]
>   949   if ((cur_used_bytes + alloc_byte_size) >
> marking_initiating_used_threshold) {
> that determines whether marking should start, that decision is
> externalized into a G1IHOPControl class with a
> get_conc_mark_start_threshold() method.
> This allows flexible replacement of the IHOP calculation algorithm
> depending on some switch using a factory method.
> In addition to that, this change tracks and passes several information
> IHOPControl instances need, like allocation between gcs, mutator time
> from initial mark to the first mixed gc, and others.
> The change also adds some test.
> It depends on all my recent patches in this area, namely:
> 8140689: Skip last young-only gc if nothing to do in the mixed gc phase
> 8140597: Forcing an initial mark causes G1 to abort mixed collections
> 8140585: PLAB statistics are flushed too late
> 8139874: After G1 Full GC, the next GC is always a young-only GC
> 8138740: Start initial mark right after mixed GC if needed
> The problem is that it expects (and verifies) that the GC pauses are
> executed in the "correct" order.
> There is no behavioral change in this CR.
> CR:
> https://bugs.openjdk.java.net/browse/JDK-8136681
> Webrev:
> http://cr.openjdk.java.net/~tschatzl/8136681/webrev/

In g1CollectorPolicy.cpp
  156   _initial_mark_to_mixed()
InitialMarkToMixedTimeTracker has a non-trivial default constructor so 
you don't need to call it explicitly.

  296 G1CollectorPolicy::~G1CollectorPolicy() {
  297   if (_ihop_control != NULL) {
  298     delete _ihop_control;
  299   }
  300 }
There is no need to null check before delete.

  544 uint G1CollectorPolicy::bounded_young_list_target_length(size_t 
rs_lengths, size_t* unbounded_target_length) const {
  545   // Calculate the absolute and desired min bounds.
Would it make sense to split bounded_young_list_target_length into
uint unbounded_young_list_target_length(size_t rs_lengths) const;
uint bound_young_list_target_length(uint unbounded) const;

update_young_list_max_and_target_length could then become

uint unbounded_young = unbounded_young_list_target_length(size_t 
_young_list_target_length = bound_young_list_target_length(unbounded_young);
return unbounded_young;

this way you could get rid of the output parameter which looks kind of ugly.

  920   // We abort the marking phase.
We skip doing mixed gcs sounds more appropriate here, we've successfully 
completed marking, right?

  987         marking_initiating_used_threshold,
  988         (double) marking_initiating_used_threshold / 
_g1->capacity() * 100,
  989         source);
since G1IHOPControl has an _ihop_percent member, could you add an 
accessor for it and use it in the ergo logging instead of:
(double) marking_initiating_used_threshold / _g1->capacity() * 100,

1039   double app_time_ms = 1.0;
why not just move the calculation of app_time_ms outside the use_stats 
scope as well?

1219   double marking_to_mixed_time = -1.0;
1220   if (!collector_state()->last_gc_was_young() && 
_initial_mark_to_mixed.has_result()) {
1221     marking_to_mixed_time = _initial_mark_to_mixed.last_marking_time();
1222     assert(marking_to_mixed_time > 0.0,
1223            "Initial mark to mixed time must be larger than zero but 
is %.3f",
1224            marking_to_mixed_time);
1225   }
1226   // Only update IHOP information on regular GCs.
1227   if (update_stats) {
1228     update_ihop_statistics(marking_to_mixed_time,

Since you are only setting marking_to_mixed_time at line 1221 -1 is 
passed to update_ihop_statistics fairly regularly.
Would it make sense to break out update_time_to_mixed and move it inside 
the 1220-1225 if-block?

  289   class InitialMarkToMixedTimeTracker {
Would you mind moving this into a separate file?
I would almost prefer if this code was made more general somehow but 
let's skip that for now, but giving it the exposure of its own file 
might make it more discoverable for alternate uses and could trigger 
someone else to reuse the code.

I'm sure a VALUE_OBJ_CLASS_SPEC on the TimeTracker will make someone 
really happy.

Can you file an enhancement to unify G1CollectorPolicy::PauseKind and 
G1YCType/G1YCTypeHelper (g1YCTypes.hpp)


You never use the forward declared G1Predictions (but I guess it's used 
by adaptive ihop in the next patch?)


You never use the included g1Predictions.hpp (but I guess it's used by 
adaptive ihop in the next patch?)

   55                 (double) get_conc_mark_start_threshold() / 
_target_occupancy * 100.0,
why not use _ihop_percent here?


> Testing:
> jprt, vm.gc, lots of manual testing, new VM test
> Note that SQE will create additional tests.
> Thanks,
>    Thomas

More information about the hotspot-gc-dev mailing list