RFR (M): 8060697: Improve G1 Heap Growth Heuristics

Jon Masamitsu jon.masamitsu at oracle.com
Mon Nov 30 20:10:25 UTC 2015


Tom,

http://cr.openjdk.java.net/~tbenson/8060697/webrev/src/share/vm/gc/g1/g1CollectorPolicy.cpp.frames.html

1053 // Compute the ratio of just this last pause time to the entire 
time range stored
1054 // in the vectors.
1055 _last_pause_time_ratio =
1056 (pause_time_ms * _recent_prev_end_times_for_all_gcs_sec->num()) / 
interval_ms;


_last_pause_time_ratio is the ratio of the last pause over the
average interval in the truncated sequence?  By the latter
I mean

(interval_ms / _recent_prev_end_times_for_all_gcs_sec->num())

If the truncated sequence has N sample and "interval_ms" is
measured from the oldest sample, I'm calling interval_ms / N
the average interval.

Is my description correct?  Why do you prefer that to the most recent
pause time ratio?

Should the 1*M below be 1 region size?

1545     const size_t min_expand_bytes = 1*M;


As the uncommitted space in the heap drops, the grow rate drops.


1550     size_t expand_bytes_via_pct =
1551       uncommitted_bytes * G1ExpandByPercentOfAvailable / 100;


The scale_factor will increase that by up to a factor of 2, the policy
seems to grow slowly to the maximum.  Is there a reason not to get
to the maximum heap size quickly?

Jon


On 11/25/2015 06:06 AM, Tom Benson wrote:
> Hi Kim,
> Thanks very much for the review.  I've implemented all your suggestions.
> Down
> About this:
>
>> I suspect you are introducing some implicit conversions that will cause
>> problems for the SAP folks; see discussion of 8143215:
>
> ... I think there's one, which is:
>
>     expand_bytes = expand_bytes * scale_factor;
>
> scale_factor is explicitly limited to being between 0.2 and 2.0, and 
> expand_bytes is fraction of the heap size, so there's no chance of 
> overflow.  Would you object to the static cast in this case?  How 
> about with a comment?
>
> Tom
>
> On 11/24/2015 9:55 PM, Kim Barrett wrote:
>> On Nov 23, 2015, at 10:02 PM, Tom Benson <tom.benson at oracle.com> wrote:
>>> Hi,
>>> Here is a proposed change to the G1 heap growth code for review. 
>>> I've added a detailed description to the CR, but here is the short 
>>> version: After a GC pause, the average ratio of time spent in recent 
>>> GC pauses vs overall time is computed. If it exceeds GCTimeRatio, 
>>> the heap is expanded by a fixed amount.  With the new code, some 
>>> deficiencies in the ratio tracking are addressed, and the expansion 
>>> size is scaled according to how much the desired ratio is, on 
>>> average, exceeded by.  The target ratio itself is also scaled at the 
>>> lowest heap sizes.
>>>
>>> The case that triggered this was actually JDK-8132077, where the 
>>> JVM'08 Compress benchmark saw a 40% degradation.  It was due to the 
>>> heap being about half the size in some runs, because of the way heap 
>>> growth worked.
>>>
>>> I'm still collecting the final performance data for this version, 
>>> and will attach it to the CR.  Earlier experimental versions showed 
>>> good improvements in consistency of heap sizes.  A couple of 
>>> benchmarks average a percentage point or two lower, while others 
>>> improve by that much or more.  No growth percentage or scaling is 
>>> going to be ideal for every test, but the goal was to maintain 
>>> performance without growing too large. In fact, some tests now use 
>>> much smaller heaps.
>>>
>>> CR:
>>> https://bugs.openjdk.java.net/browse/JDK-8060697
>>> Webrev:
>>> http://cr.openjdk.java.net/~tbenson/8060697/webrev/
>> Generally looks good; just a few very minor things, most of which you 
>> can
>> take or ignore as you prefer.  I don't need a new webrev for any of 
>> these.
>>
>> The comments were very helpful in understanding what's going on.
>>
>> I suspect you are introducing some implicit conversions that will cause
>> problems for the SAP folks; see discussion of 8143215: gcc 4.1.2: fix 
>> three
>> issues breaking the build.  But the resolution for that is still being
>> discussed, and we don't have an easy way to discover these for 
>> ourselves, so
>> I don't think you should worry about it here right now.
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/share/vm/gc/g1/g1CollectorPolicy.cpp
>> 1571       static double const MinScaleDownFactor = 0.2;
>> 1572       static double const MaxScaleUpFactor = 2;
>> 1573       static double const StartScaleDownAt = _gc_overhead_perc;
>> 1574       static double const StartScaleUpAt = _gc_overhead_perc * 1.5;
>> 1575       static double const ScaleUpRange = _gc_overhead_perc * 2.0;
>>
>> I suggest these not be static.
>>
>> It doesn't really matter for the first two.
>>
>> But for the others, there is a hidden cost to making them static, due to
>> some compilers ensuring thread-safe initialization.  C++11 mandates
>> thread-safe initialization of function scoped statics.  gcc has 
>> implemented
>> that starting circa gcc4.0 (if I recall correctly), controlled by a CLA
>> (-f[no]-threadsafe-statics).  Visual Studio 2013 also includes this 
>> feature,
>> as part of their incremental rollout of C++11 (and later) features.  
>> I don't
>> know about other compilers.
>>
>> The cost of making them static is likely at least comparable to 
>> computing
>> them.  And making them static implies the _gc_overhead_perc is 
>> effectively a
>> constant, which appears to be true today, but who knows what will happen
>> tomorrow.
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/share/vm/gc/g1/g1CollectorPolicy.cpp
>> 1587         scale_factor = MAX2<double>(scale_factor, 
>> MinScaleDownFactor);
>> 1590         scale_factor = MIN2<double>(scale_factor, 
>> MaxScaleUpFactor);
>>
>> The explicit double template parameter isn't needed here, since the
>> arguments are already both doubles.
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/share/vm/gc/g1/g1CollectorPolicy.cpp
>> 1525     threshold = (threshold * ((double)_g1->capacity() / 
>> (double)(_g1->max_capacity() / 2)));
>>
>> This might be easier to read if it used "threshold *= ...".
>>
>> ------------------------------------------------------------------------------ 
>>
>> src/share/vm/gc/g1/g1CollectorPolicy.cpp
>> 1526     threshold = MAX2<double>(threshold, 1);
>>
>> The explicit double template parameter wouldn't be needed if "1" was
>> replaced with "1.0".
>>
>> ------------------------------------------------------------------------------ 
>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-gc-dev/attachments/20151130/0ac5816f/attachment.htm>


More information about the hotspot-gc-dev mailing list