EVALUATION
The problem occurs only for Spaces in the young gen that are non-empty at the start of a full gc. Since -XX:+ScavengeBeforeFullGC is enabled by default, full GCs occur after a scavenge which normally empties eden. So 95% of the time, only To space contains data while Eden and From space are empty.
For each non-empty space in the young gen, the summary phase currently clears data from space->bottom() to space->top() (the top() value before the start of the full gc). However, it is only necessary to clear from space->bottom() to the the "new top" for the space, where "new top" refers to the value computed by the first pass of the summary phase (which computes values to compact the space completely into itself). The "new top" is usually significantly less than space->top(), so less clearing can be done.
|
SUGGESTED FIX
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -1635,7 +1635,7 @@
const size_t live = pointer_delta(_space_info[id].new_top(),
space->bottom());
const size_t available = pointer_delta(target_space_end, *new_top_addr);
- if (live <= available) {
+ if (live > 0 && live <= available) {
// All the live data will fit.
if (TraceParallelOldGCSummaryPhase) {
tty->print_cr("summarizing %d into old_space @ " PTR_FORMAT,
@@ -1645,16 +1645,18 @@
space->bottom(), space->top(),
new_top_addr);
- // Reset the new_top value for the space.
- _space_info[id].set_new_top(space->bottom());
-
// Clear the source_chunk field for each chunk in the space.
+ HeapWord* const new_top = _space_info[id].new_top();
+ HeapWord* const clear_end = _summary_data.chunk_align_up(new_top);
ChunkData* beg_chunk = _summary_data.addr_to_chunk_ptr(space->bottom());
- ChunkData* end_chunk = _summary_data.addr_to_chunk_ptr(space->top() - 1);
- while (beg_chunk <= end_chunk) {
+ ChunkData* end_chunk = _summary_data.addr_to_chunk_ptr(clear_end);
+ while (beg_chunk < end_chunk) {
beg_chunk->set_source_chunk(0);
++beg_chunk;
}
+
+ // Reset the new_top value for the space.
+ _space_info[id].set_new_top(space->bottom());
}
}
|