RFR(L): 6484965: G1: piggy-back liveness accounting phase on marking
John Cuthbertson
john.cuthbertson at oracle.com
Wed Dec 21 17:08:14 UTC 2011
Hi Bengt,
That's a good observation. I guess it is possible but I haven't seen it
in practice (though I was typically only using 4 threads when debugging
a verification failure). It won't do any harm so I'll add the locking.
Thanks,
JohnC
On 12/21/2011 2:05 AM, Bengt Rutisson wrote:
>
> Hi John,
>
> Thanks for updating your fix! Looks good.
>
> One quesiton:
> In concurrentMark.cpp it seems to me that the
> VerifyLiveObjectDataHRClosure could get the same kind of messed up
> output that Tony just fixed with 7123165 for the VerifyLiveClosure in
> heapRegion.cpp. There are several workers simultaneously doing the
> verification, right? Is it worth adding the same kind of locking that
> Tony added?
>
> Bengt
>
> On 2011-12-20 20:16, John Cuthbertson wrote:
>> Hi Bengt,
>>
>> As I mentioned earlier - thanks for the code review. I've applied
>> your suggestions, merged with the the latest changeset in
>> hsx/hotspot-gc/hotspot (resolving any conflicts), fixed the int <->
>> size_t issue you also mentioned, and retested using the GC test
>> suite. A new webrev can be found at:
>> http://cr.openjdk.java.net/~johnc/6484965/webrev.2/
>>
>> Specific replies are inline.
>>
>> On 11/28/11 05:07, Bengt Rutisson wrote:
>>>
>>> John,
>>>
>>> A little late, but here are some comments on this webrev. I know you
>>> have some more improvements to this change coming, but overall I
>>> think it looks good. Most of my comments are just minor coding style
>>> comments.
>>>
>>> Bengt
>>>
>>> concurrentMark.hpp
>>>
>>> Rename ConcurrentMark::clear() to ConcurrentMark::clear_mark() or
>>> ConcurrentMark::unmark()? The commment you added is definitely
>>> needed to understand what this method does. But it would be even
>>> better if it was possible to get that from the method name itself.
>>
>> Done.
>>
>>> It seems like everywhere we use count_marked_bytes_for(int worker_i)
>>> we almost directly use the array returned to index with the heap
>>> region that we are interested in. How about wrapping all of this is
>>> in something like count_set_marked_bytes_for(int worker_i, int
>>> hrs_index) and count_get_marked_bytes_for(int worker_i, int
>>> hrs_index) ? That way the data structure does not have to be exposed
>>> outside ConcurrentMark. It would mean that
>>> ConcurrentMark::count_region() would have to take a worker_i value
>>> instead of a marked_bytes_array.
>>
>> I did not do this. I embed the marked_bytes array for a worker into
>> the CMTask for that worker to save a de-reference. This was one of
>> the requests from the original code walk-through. Avoiding the
>> de-reference in the CMTask::do_marking_step() shaves a couple of
>> points off the marking time. I think your suggestion would reinstate
>> the de-reference again and we would lose those few percentage points
>> again.
>>
>>> If you don't agree with the suggestion above I would suggest to
>>> change the name from count_marked_bytes_for() to
>>> count_marked_bytes_array_for() since in every place that it is being
>>> called the resulting value is stored in a local variable called
>>> marked_bytes_array, which seems like a more informative name to me.
>>
>> Done. I agree - the new name sounds better.
>>
>>> I think this comment:
>>>
>>> // As above - but we don't know the heap region containing the
>>> // object and so have to supply it.
>>> inline bool par_mark_and_count(oop obj, int worker_i);
>>>
>>> should be something like "we don't know the heap region containing
>>> the object so we will have to look it up".
>>>
>>> Same thing here:
>>>
>>> // As above - but we don't have the heap region containing the
>>> // object, so we have to supply it.
>>> // Should *not* be called from parallel code.
>>> inline bool mark_and_count(oop obj);
>>>
>>>
>>
>> Comments were changed to:
>>
>>
>>> concurrentMark.cpp
>>>
>>> Since you are changing CalcLiveObjectsClosure::doHeapRegion()
>>> anyway, could you please remove this unused code (1393-1397):
>>>
>>> /*
>>> gclog_or_tty->print_cr("Setting bits from %d/%d.",
>>> obj_card_num - _bottom_card_num,
>>> obj_last_card_num - _bottom_card_num);
>>> */
>>>
>>>
>>
>> Done.
>>
>>> What about the destructor ConcurrentMark::~ConcurrentMark() ? I
>>> remember Tony mentioning that it won't be called. Do you still want
>>> to keep the code?
>>
>> I removed the entire destructor - I don't see it being called in the
>> experiments I've run.
>>
>>> FinalCountDataUpdateClosure::set_bit_for_region()
>>> Probably not worth it, but would it make sense to add information in
>>> a startsHumongous HeapRegion to be able to give you the last
>>> continuesHumongous region? Since we know this when we set the
>>> regions up it seems like a waste to have to iterate over the region
>>> list to find it.
>>
>> If you read the original comment - the original author did not want
>> to make any assumptions about the internal field values of the
>> HeapRegions spanned by a humongous object and so used the loop
>> technique. I think you are correct and I now use the information in
>> the startsHumongous region to find the index of the last
>> continuesHumongous region spaned by the H-obj.
>>
>>> G1ParFinalCountTask
>>> To me it is a bit surprising that we mix in the verify code inside
>>> this closure. Would it be possible to extract this code out somehow?
>>
>> I did it this way to avoid another iteration over the heap regions.
>> But it probably does make more sense to separate them and use another
>> iteration to do the verify. Done.
>>
>>> Line 3378: "// Use fill_to_bytes". Is this something you plan on doing?
>>
>> I removed the comment. I was thinking of doing this as fill_to_bytes
>> is typically implemented using (a possibly specialized version of)
>> memset. But it's probably not worth it in this case.
>>
>>> G1ParFinalCountTask::work()
>>> Just for the record. I don't really like the way we have to set up
>>> both a VerifyLiveObjectDataHRClosure and a Mux2HRClosure even though
>>> we will only use them if we have VerifyDuringGC enabled. I realize
>>> it is due to the scoping, but I still think it obstucts the code
>>> flow and introduces unnecessary work. Unfortunately I don't have a
>>> good suggestion for how to work around it.
>>>
>>> Since both VerifyLiveObjectDataHRClosure and a Mux2HRClosure are
>>> StackObjs I assume it is not possible to get around the issue with a
>>> ResourceMark.
>>
>> Now that the verification is performed in a separate iteration of the
>> heap regions there's no need to create the
>> VerifyLiveObjectDataHRClosure and Mux2HRClosure instances here.
>> Done. I have also removed the now-redundant Mux2HRClosure.
>>
>> Hopefully the new webrev addresses these comments.
>>
>> Thanks again for looking.
>>
>> JohnC
>>
>
More information about the hotspot-gc-dev
mailing list