RFR (S/M): 8178105: Switch mark bitmaps during Remark
Stefan Johansson
stefan.johansson at oracle.com
Tue Apr 3 12:49:21 UTC 2018
On 2018-04-03 14:25, Thomas Schatzl wrote:
> Hi Stefan,
>
> On Tue, 2018-04-03 at 12:58 +0200, Stefan Johansson wrote:
>> Hi Thomas,
>>
>> On 2018-03-29 16:35, Thomas Schatzl wrote:
>>> Hi all,
>>>
>>> can I have reviews for this small change that makes G1 switch the
>>> mark bitmaps already during the Remark pause as opposed waiting
>>> until
>>> Cleanup?
>>>
>>> This is the last step before G1 can reclaim regions at Remark,
>>> which means that empty regions can be cleaned up more more quickly
>>> than before (JDK-8154528, coming soon :)).
>>>
>>> The main changes apart from actually switching the bitmaps consist
>>> of updating the liveness information, i.e. how many bytes are live
>>> in a region, now already available at Remark since JDK-8197850,
>>> also at the same time.
>>>
>>> Previously G1 used the Rebuild Remsets phase to calculate that at
>>> the same time.
>>>
>>> I could not find significant differences in timing.
>>>
>>> This change depends on the recent g1ConcurrentMark refactorings,
>>> particularly JDK-8200234.
>>>
>>> CR:
>>> https://bugs.openjdk.java.net/browse/JDK-8178105
>>> Webrev:
>>> http://cr.openjdk.java.net/~tschatzl/8178105/
>> Looks good, but a few comments:
>>
>> src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
>> 1031 for (uint i = region_idx; i < (region_idx +
>> num_regions_in_humongous); i++) {
>> 1032 HeapRegion* const r = _g1h->region_at(i);
>> 1033 size_t const words_to_add = MIN2(HeapRegion::GrainWords,
>> marked_words);
>> 1034 r->add_to_marked_bytes(words_to_add * HeapWordSize);
>> 1035 marked_words -= words_to_add;
>> 1036 }
>> Could be nice to assert that marked_words is zero after the
>> iteration, i.e. that everything got distributed
>
> Done.
>
>> and maybe also that marked_words is greater than 0 during the
>> iteration.
>
> Can't check that - both sizes are unsigned type. The MIN2() in line
> 1033 prevents words_to_add to ever be greater than marked_words, so I
> think a check like that will be useless.
Yes, but it could be if equal marked_words will be 0 and I want to
assert that this never happens before the last iteration.
>
> I added a different kind of check that verifies what you probably
> thought of, and that is that the number of words to add to the current
> region must always be larger than zero. If it is zero, there is
> something really wrong.
Exactly, that's what I wanted. But I don't see that check now, just
having a assert(marked_words != 0, "") on row 1032 would be enough.
>
>>
>> 1047 log_trace(gc)("Added " SIZE_FORMAT " words to region %u
>> (%s)", marked_words, region_idx, hr->get_type_str());
>> I think the logging should use at least one more tag, maybe "region"
>> or "marking", but you probably know what makes most sense in this
>> area. I also think it would be nice if we got this same log-line for
>> all regions. Now we get this for "normal" regions, but we get
>> "Distributing..." for humongous start regions and "Not Added..." for
>> humongous continuous. So I would suggest adding the same log-line to
>> the distribute-function after line 1034.
>
> Done.
Sorry for being picky but the current solution won't print anything for
continuous humongous. Adding the log to distribute_marked_bytes() would
solve this and we would still get info on region type so I see no need for:
1052 log_trace(gc, marking)("Adding " SIZE_FORMAT " words to
humongous start region %u (%s), word size %d (%f)",
1053 marked_words, region_idx,
hr->get_type_str(),
1054 oop(hr->bottom())->size(),
(double)oop(hr->bottom())->size() / HeapRegion::GrainWords);
>
>> 1045 if (!hr->is_humongous()) {
>> Since the comment talks about humongous regions I would prefer not
>> negating the statement and have something like:
>> if (hr->is_humongous()) {
>> if (hr->is_starts_humongous()) {
>> distribute_marked_bytes(hr, marked_words);
>> } else {
>> assert(marked_words == 0, "continuous humongous are not accounted
>> separately");
>> }
>> } else {
>> hr->add_to_marked_bytes(marked_words * HeapWordSize);
>> log_trace(gc)("Added " SIZE_FORMAT " words to region %u (%s)",
>> marked_words, region_idx, hr->get_type_str());
>> }
>>
>> 1058 }
>> Newline before public :)
>>
>> 1686 if (mark_completed) {
>> 1687 is_alive = &is_alive_prev;
>> 1688 } else {
>> 1689 is_alive = &is_alive_next;
>> 1690 }
>> 1691 _gc_tracer_cm->report_object_count_after_gc(is_alive);
>>
>> I would prefer moving the call into the if and only setup the closure
>> when needed:
>> if (mark_completed) {
>> G1ObjectCountIsAliveClosure is_alive(_g1h);
>> _gc_tracer_cm->report_object_count_after_gc(&is_alive);
>> } else {
>> G1CMIsAliveClosure is_alive(_g1h);
>> _gc_tracer_cm->report_object_count_after_gc(&is_alive);
>> }
>
> All fixed.
>
> Webrevs:
> http://cr.openjdk.java.net/~tschatzl/8178105/webrev.0_to_1/ (diff)
> http://cr.openjdk.java.net/~tschatzl/8178105/webrev.1/ (full)
Apart from the small things above this looks great.
Thanks,
Stefan
> Testing:
> locally ran all gc/g1 jtreg tests with no problems
>
> Thomas
>
More information about the hotspot-gc-dev
mailing list