RFR (M/L): 8247928: Refactor G1ConcurrentMarkThread for mark abort (JDK-8240556)
Kim Barrett
kim.barrett at oracle.com
Thu Sep 3 17:17:02 UTC 2020
> On Sep 3, 2020, at 6:07 AM, Thomas Schatzl <thomas.schatzl at oracle.com> wrote:
> On 03.09.20 09:24, Kim Barrett wrote:
>> It seems backward that the phase functions return true to indicate aborted,
>> overflow, or whatever, and return false for successful completion. And
>> there's no mention of what the return values are in the description in the
>> header file.
>
> I think the code is easier to read without the need to always negate the result. Ie. in the following example
>
> if (!phase1) return;
> if (!phase2) return;
>
> the "!" detracts imho from reading the steps.
>
> Another option I can see could be a macro hiding all this, e.g.
>
> EXEC(phase1);
> EXEC(phase2);
>
> but I kind of dislike that even more.
>
> Added documentation.
I agree a macro is not the way to go here. I'm less bothered by the need for
lots of preceeding "!" than you are, but I certainly see your point. So I'm
okay with the code as is, now that there's a comment to set expectations.
> http://cr.openjdk.java.net/~tschatzl/8247928/webrev.1_to_2 (diff)
> http://cr.openjdk.java.net/~tschatzl/8247928/webrev.2 (full)
I like the overall approach a lot. Thanks for doing this cleanup.
Although I have a number of comments, there's nothing major here.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp
190 uint iter = 1;
191 while (true) {
...
209 log_info(gc, marking)("Concurrent Mark Restart for Mark Stack Overflow (iteration #%u)",
210 iter++);
I think that's the only use of iter, and that it's not used after the loop.
How about instead
for (uint iter = 1; true; ++iter) {
and remove the increment in the logging statement.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp
191 while (true) {
...
211 }
212
213 Ticks mark_end = Ticks::now();
214 log_info(gc, marking)("Concurrent Mark (%.3fs, %.3fs) %.3fms",
215 mark_start.seconds(), mark_end.seconds(),
216 (mark_end - mark_start).seconds() * 1000.0);
This is a change to the logging. Some consequences I like, others I'm not so
sure about. You talked about some of this in the RFR description, but I
want to go through it carefully here.
- This now includes the remark pause in the time, where previously that
seemed to be intentionally excluded. I don't know the rationale for that
exclusion, but it was pretty clearly intentional since it intentionally (per
comment) contorted the code somewhat. So it's hard to decide whether this is
okay. The remark time could be excluded though by capturing the mark_end
time just before calling subphase_remark().
- It only does this logging once, rather than on each iteration. That seems
good; as you pointed out in the RFR, multiples are pretty likely handled
wrong by some uses.
- This logging no longer happens if marking is aborted by remark. That's
now consistent with other abort cases, so probably an improvement.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp
137 while (!should_terminate()) {
138 if (wait_for_next_cycle()) {
139 break;
140 }
This could instead just be
while (!wait_for_next_cycle()) { ...
But I already thought the sense of the wait_for_next_cycle result was
backward, and this makes an even stronger case for that. I think better
would be to reverse the sense of the result and use
while (wait_for_next_cycle()) { ...
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp
65 bool phase_concurrent_cycle_start();
Unused and undefined.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp
63 // ConcurrentGCBreakpoints must not be placed before the the root
64 // region scan phase too for this reason.
This comment seems misplaced here. I think it belongs in the implementation
of full_concurrent_cycle_do, in conjunction with the comment about not
returning before the scan root regions phase.
I think the rest of the comment about STS &etc also seems misplaced here and
should be similarly moved (more or less where it used to be).
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp
66 bool phase_clear_cld_claimed_marks();
The result of this function is unused, because of the restriction against
returning before the scan root regions phase. I think I'd prefer it return
void, to make it clear there's nothing to be done with it. Even though that
makes its signature different from all the phase functions.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp
81 // Perform a full concurrent cycle.
This comment seems kind of vacuous. The function also in some sense doesn't
even do that, since it doesn't include the start/end parts.
------------------------------------------------------------------------------
src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp
70 bool mark_loop_needs_restart() const;
This one seems out of order or otherwise misplaced here. Seems like it
should be after subphase_remark. Or maybe it shouldn't be in the phase
function section at all.
------------------------------------------------------------------------------
More information about the hotspot-gc-dev
mailing list