RFR(L): 6484965: G1: piggy-back liveness accounting phase on marking

Bengt Rutisson bengt.rutisson at oracle.com
Mon Nov 28 13:07:20 UTC 2011


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.

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.

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.

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);




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);
         */



What about the destructor ConcurrentMark::~ConcurrentMark() ? I remember 
Tony mentioning that it won't be called. Do you still want to keep the code?


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.

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?

Line 3378: "// Use fill_to_bytes". Is this something you plan on doing?

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.




On 2011-11-15 19:44, John Cuthbertson wrote:
> Hi Everyone,
>
> I have a new webrev for these changes which includes all the code 
> review comments made during the code walkthrough and subsequently. The 
> new webrev can be found at: 
> http://cr.openjdk.java.net/~johnc/6484965/webrev.1/
>
> Changes include:
> * Accessor function type changes (they return a pointer to the card 
> bitmap for a task rather than a reference).
> * A card bitmap and marked_bytes array is now embedded into the CMTask 
> to avoid an extra dereference.
> * Marking and counting have been combined in a single operation.
> * Mark/count routines have been placed in the .inline.hpp file.
> * Aggregation is now down in parallel and clearing of the count data 
> is performed at the same time.
> * GC Lab retirment - there's no need to be super accurate - I don't 
> need a specific routine - and can use one of the existing count 
> routines (count_region).
>
> Note this version of the code still has a card bitmap per task/worker 
> id and so incurs a footprint penalty. Removing the card bitmap(s) used 
> to scrub RSets will be done as a separate change.
>
> Testing: GC test suite and Kitchensink with a very low marking 
> threshold - 2%.
>
> Thanks,
>
> JohnC
>
> On 10/03/11 16:09, John Cuthbertson wrote:
>> Hi Everyone,
>>
>> Can I have a couple of volunteers review the changes for this CR? The 
>> webrev can be found at: 
>> http://cr.openjdk.java.net/~johnc/6484965/webrev.0/
>>
>> Summary:
>> During some big application runs we were seeing some excessively long 
>> concurrent counting times. These long counting times were increasing 
>> the cycle time of concurrent marking and increasing the risk of 
>> evacuation failure. It was suggested that, rather than having a 
>> separate phase that walks the marking bitmap to calculate the amount 
>> of live data etc, we could track this information in some per marking 
>> task/worker thread data structures and update the information as 
>> objects were marked. These changes implement that scheme. The 
>> original bitmap walking code has been retained but turned into a 
>> verification mechanism that is enabled using 
>> -XX:+UnlockDiagnosticVMOption -XX:+VerifyDuringGC.
>>
>> Testing: GC test suite with a low marking threshold (10%); OpenDS, 
>> KitchenSink, and jprt with the additional verification code enabled.
>>
>> JohnC
>>
>>
>>
>>
>




More information about the hotspot-gc-dev mailing list