RFR: 8071462: Remove G1ParGCAllocator::alloc_buffer_waste

Michail Chernov michail.chernov at oracle.com
Wed Apr 15 18:42:07 UTC 2015

Hi Thomas,

I tried to make all what you said.
Webrev: http://cr.openjdk.java.net/~dpochepk/~mchernov/8071462/webrev.02/

ParGCAllocBuffer::add_undo_waste and 
ParGCAllocBuffer::undo_last_allocation were made as protected members.

ParGCAllocBuffer::undo_allocation now does the same as 
ParScanThreadState::undo_alloc_in_to_space and 

G1ParGCAllocator has virtual G1PLABWasteStat wasted() = 0; method which 
must be implemented in all heirs.

Introduced new class G1PLABWasteStat (g1Allocator.hpp) that retrieves 
wasted and undo wasted values from allocation buffers. If new class is 
not acceptable there, I can add 2 virtual methods to G1ParGCAllocator 
for retrieving wasted and undo wasted values.


On 15.04.2015 6:53, Thomas Schatzl wrote:
> Hi Michail,
> On Tue, 2015-04-14 at 21:39 +0300, Michail Chernov wrote:
>> Hi Thomas,
>> On 13.04.2015 22:21, Thomas Schatzl wrote:
>>> Hi Michail,
>>> On Mon, 2015-04-13 at 16:40 +0300, Michail Chernov wrote:
>>>> Hi,
>>>> Still have no response, please take a look!
>>>> Michail
>>>> On 08.04.2015 15:58, Michail Chernov wrote:
>>>>> Hi,
>>>>> Please could someone review this update?
>>>>> Changes were updated - fixed code formatting.
>>>>> http://cr.openjdk.java.net/~akulyakh/8071462/webrev.01/
>>>>> Thanks,
>>>>> Michail
>>>>> On 07.04.2015 17:26, Michail Chernov wrote:
>>>>>> Hi,
>>>>>> Can I have couple of reviews for next change?
>>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8071462
>>>>>> Webrev:
>>>>>> http://cr.openjdk.java.net/~eistepan/~mchernov/8071462/webrev.00/
>>>>>> G1ParGCAllocator has methods add_to_alloc_buffer_waste(size_t waste)
>>>>>> and add_to_undo_waste(size_t waste) which are used wrong.
>>>>>> The main idea of fix is to track waste and undo to waste in PLAB. We
>>>>>> cannot use PLABStats to store such values because PLABStats is shared
>>>>>> between all PLAB and cannot store separate values of waste in itself.
>>>>>> We can get waste and undo to waste values from ParGCAllocBuffer
>>>>>> before ParGCAllocBuffer::flush_and_reture() which is called from
>>>>>> G1ParScanThreadState destructor (destructor calls
>>>>>> G1DefaultParGCAllocator::retire_alloc_buffers which calls
>>>>>> ParGCAllocBuffer::flush_and_reture() ). Now destructor calls separate
>>>>>> method which is invoked before G1ParScanThreadState destruction, so
>>>>>> we can get waste and undo to waste to get termination stats.
>>>>>> Also removed unused methods in G1ParScanThreadState:
>>>>>> add_to_alloc_buffer_waste and  add_to_undo_waste.
>>>>>> Fix was checked locally with -XX:+UseG1GC -XX:+PrintTerminationStats
>>>>>> and was checked by JPRT.
>>> - I am not completely clear why the change keeps
>>> G1ParGCAllocator::_alloc_buffer_waste and G1ParGCAllocator::_undo_waste.
>>> They are identical to ParGCAllocBuffer::_undo_waste and
>>> ParGCAllocBuffer::_wasted anyway?
>> G1ParGCAllocator can contain different allocation buffers (which can be
>> accessed by G1ParGCAllocator::alloc_buffer which is pure virtual). So,
>> _alloc_buffer_waste and _undo_waste are used to store sums of all values
>> from all buffers.
> My argument is that it is not required to (temporarily) store these
> values in G1ParGCAllocator::_alloc_buffer_waste and G1ParGCAllocator at
> all. They are purely used for some very detailed logging, so performance
> of that particular call is not really important, and the amount of extra
> work not particular large.
> So the calls could be made virtual and the implementations iterate over
> the buffers themselves.
>>> Why not let the getters access these values directly? At that point
>>> their contents seem still be valid (i.e. not "flushed" to the global
>>> PLABStats).
>> G1ResManParGCAllocator (which is in closed part) can store more than two
>> G1ParGCAllocBuffer inside.
>> G1ParScanThreadState::print_termination_stats() doesn't know anything
>> about G1ParGCAllocator heirs. Therefore there are used
>> G1ParGCAllocator::alloc_buffer_waste() and undo_waste().
>>> Then there is also no need to introduce
>>> G1ParScanThreadState::retire_alloc_buffers().
>> We cannot to use all statistics which is not flushed without
>> G1ParGCAllocator::retire_alloc_buffers(). Until this change
>> _g1_par_allocator->retire_alloc_buffers() is invoked only from
>> G1ParScanThreadState::~G1ParScanThreadState() , so statistics for all
>> ParGCAllocBuffer is not added to G1ParGCAllocator::_alloc_buffer_waste
>> and _undo_waste. Now retire_alloc_buffers() can be invoked directly
>> before printing statistics.
> Thinking about this some more, I more and more dislike this approach:
> this means that in some cases, the PLABs will be retired multiple times
> when this flag is enabled (and only then). In case of G1 this has no
> impact, because of its special G1PLAB/G1ParGCAllocBuffer implementation,
> but it seems something unexpected.
> Then there is 8040162: Avoid reallocating PLABs between GC phases in G1:
> in this change the PLAB buffers (actually the current implementation
> keeps G1ParScanThreadState instances) are kept during the entire young
> gc without any in-between retirement of the PLABs (which is the point to
> save memory)
> With the current proposed change the efficiency of this idea would be
> decreased if and only if that flag is set. Logging should not impact
> execution that much imo.
> It would be great if this change would already prepare for JDK-8040162
> instead of adding more work (unless you see another way).
>>> - In G1ParGCAllocator::undo_allocation, the calls to alloc_buffer(dest,
>>> context) could be factored out as a minor cleanup.
>>> - In G1ParGCAllocator::undo_allocation(), in the else-part, maybe the
>>> two lines
>>>         CollectedHeap::fill_with_object(obj, word_sz);
>>>         alloc_buffer(dest, context)->add_undo_waste(word_sz);
>>> could be factored into a method of ParGCAllocBuffer like
>>> undo_allocation() so that internal counter handling is completely hidden
>>> by ParGCAllocBuffer.
>> I thought that it is not good idea to mix logic of buffer and some
>> cleaning in ParGCAllocBuffer but I found that
>> ParGCAllocBuffer::retire_internal() invokes
>> CollectedHeap::fill_with_object, so I will refactor undo_allocation().
> Thanks.
> Thanks,
>    Thomas

More information about the hotspot-gc-dev mailing list