8146987: Improve Parallel GC Full GC by caching results of live_words_in_range()

A large part of time in the parallel scavenge collector is spent finding out the amount of live words within memory ranges to find out where to move an object to. Try to incrementally calculate this value.

Reviewed-by: tschatzl, mgerdin, jmasa
This commit is contained in:
Ray Alex 2016-01-28 13:30:12 +01:00 committed by Thomas Schatzl
parent ce491c9057
commit 4f42f17d9e
17 changed files with 180 additions and 81 deletions

View file

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/parallel/parMarkBitMap.hpp"
#include "gc/parallel/psCompactionManager.inline.hpp"
#include "gc/parallel/psParallelCompact.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
@ -96,7 +97,20 @@ ParMarkBitMap::mark_obj(HeapWord* addr, size_t size)
return false;
}
size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const
inline bool
ParMarkBitMap::is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const {
return cm->last_query_begin() == beg_addr;
}
inline void
ParMarkBitMap::update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const {
cm->set_last_query_begin(beg_addr);
cm->set_last_query_object(end_obj);
cm->set_last_query_return(result);
}
size_t
ParMarkBitMap::live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const
{
assert(beg_addr <= (HeapWord*)end_obj, "bad range");
assert(is_marked(end_obj), "end_obj must be live");
@ -117,6 +131,42 @@ size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const
return bits_to_words(live_bits);
}
size_t
ParMarkBitMap::live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const
{
HeapWord* last_beg = cm->last_query_begin();
oop last_obj = cm->last_query_object();
size_t last_ret = cm->last_query_return();
if (end_obj > last_obj) {
last_ret = last_ret + live_words_in_range_helper((HeapWord*)last_obj, end_obj);
last_obj = end_obj;
} else if (end_obj < last_obj) {
// The cached value is for an object that is to the left (lower address) of the current
// end_obj. Calculate back from that cached value.
if (pointer_delta((HeapWord*)end_obj, (HeapWord*)beg_addr) > pointer_delta((HeapWord*)last_obj, (HeapWord*)end_obj)) {
last_ret = last_ret - live_words_in_range_helper((HeapWord*)end_obj, last_obj);
} else {
last_ret = live_words_in_range_helper(beg_addr, end_obj);
}
last_obj = end_obj;
}
update_live_words_in_range_cache(cm, last_beg, last_obj, last_ret);
return last_ret;
}
size_t
ParMarkBitMap::live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const
{
// Try to reuse result from ParCompactionManager cache first.
if (is_live_words_in_range_in_cache(cm, beg_addr)) {
return live_words_in_range_use_cache(cm, beg_addr, end_obj);
}
size_t ret = live_words_in_range_helper(beg_addr, end_obj);
update_live_words_in_range_cache(cm, beg_addr, end_obj, ret);
return ret;
}
ParMarkBitMap::IterationStatus
ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure,
idx_t range_beg, idx_t range_end) const