8328101: Parallel: Obsolete ParallelOldDeadWoodLimiterMean and ParallelOldDeadWoodLimiterStdDev

Reviewed-by: tschatzl, iwalulya, sjohanss
This commit is contained in:
Albert Mingkun Yang 2024-03-21 15:47:55 +00:00
parent 581b1e29ae
commit 16ed191329
7 changed files with 26 additions and 236 deletions

View File

@ -79,13 +79,6 @@ void ParallelArguments::initialize() {
}
}
// Par compact uses lower default values since they are treated as
// minimums. These are different defaults because of the different
// interpretation and are not ergonomically set.
if (FLAG_IS_DEFAULT(MarkSweepDeadRatio)) {
FLAG_SET_DEFAULT(MarkSweepDeadRatio, 1);
}
if (FLAG_IS_DEFAULT(ParallelRefProcEnabled) && ParallelGCThreads > 1) {
FLAG_SET_DEFAULT(ParallelRefProcEnabled, true);
}

View File

@ -45,16 +45,6 @@
"Use maximum compaction in the Parallel Old garbage collector " \
"for a system GC") \
\
product(size_t, ParallelOldDeadWoodLimiterMean, 50, \
"The mean used by the parallel compact dead wood " \
"limiter (a number between 0-100)") \
range(0, 100) \
\
product(size_t, ParallelOldDeadWoodLimiterStdDev, 80, \
"The standard deviation used by the parallel compact dead wood " \
"limiter (a number between 0-100)") \
range(0, 100) \
\
product(bool, PSChunkLargeArrays, true, \
"Process large arrays in chunks")

View File

@ -139,14 +139,6 @@ SpaceInfo PSParallelCompact::_space_info[PSParallelCompact::last_space_id];
SpanSubjectToDiscoveryClosure PSParallelCompact::_span_based_discoverer;
ReferenceProcessor* PSParallelCompact::_ref_processor = nullptr;
double PSParallelCompact::_dwl_mean;
double PSParallelCompact::_dwl_std_dev;
double PSParallelCompact::_dwl_first_term;
double PSParallelCompact::_dwl_adjustment;
#ifdef ASSERT
bool PSParallelCompact::_dwl_initialized = false;
#endif // #ifdef ASSERT
void SplitInfo::record(size_t src_region_idx, size_t partial_obj_size,
HeapWord* destination)
{
@ -831,7 +823,6 @@ bool PSParallelCompact::initialize_aux_data() {
assert(mr.byte_size() != 0, "heap should be reserved");
initialize_space_info();
initialize_dead_wood_limiter();
if (!_mark_bitmap.initialize(mr)) {
vm_shutdown_during_initialization(
@ -867,16 +858,6 @@ void PSParallelCompact::initialize_space_info()
_space_info[old_space_id].set_start_array(heap->old_gen()->start_array());
}
void PSParallelCompact::initialize_dead_wood_limiter()
{
const size_t max = 100;
_dwl_mean = double(MIN2(ParallelOldDeadWoodLimiterMean, max)) / 100.0;
_dwl_std_dev = double(MIN2(ParallelOldDeadWoodLimiterStdDev, max)) / 100.0;
_dwl_first_term = 1.0 / (sqrt(2.0 * M_PI) * _dwl_std_dev);
DEBUG_ONLY(_dwl_initialized = true;)
_dwl_adjustment = normal_distribution(1.0);
}
void
PSParallelCompact::clear_data_covering_space(SpaceId id)
{
@ -1007,60 +988,6 @@ void PSParallelCompact::post_compact()
Universe::heap()->record_whole_heap_examined_timestamp();
}
// Return a fraction indicating how much of the generation can be treated as
// "dead wood" (i.e., not reclaimed). The function uses a normal distribution
// based on the density of live objects in the generation to determine a limit,
// which is then adjusted so the return value is min_percent when the density is
// 1.
//
// The following table shows some return values for a different values of the
// standard deviation (ParallelOldDeadWoodLimiterStdDev); the mean is 0.5 and
// min_percent is 1.
//
// fraction allowed as dead wood
// -----------------------------------------------------------------
// density std_dev=70 std_dev=75 std_dev=80 std_dev=85 std_dev=90 std_dev=95
// ------- ---------- ---------- ---------- ---------- ---------- ----------
// 0.00000 0.01000000 0.01000000 0.01000000 0.01000000 0.01000000 0.01000000
// 0.05000 0.03193096 0.02836880 0.02550828 0.02319280 0.02130337 0.01974941
// 0.10000 0.05247504 0.04547452 0.03988045 0.03537016 0.03170171 0.02869272
// 0.15000 0.07135702 0.06111390 0.05296419 0.04641639 0.04110601 0.03676066
// 0.20000 0.08831616 0.07509618 0.06461766 0.05622444 0.04943437 0.04388975
// 0.25000 0.10311208 0.08724696 0.07471205 0.06469760 0.05661313 0.05002313
// 0.30000 0.11553050 0.09741183 0.08313394 0.07175114 0.06257797 0.05511132
// 0.35000 0.12538832 0.10545958 0.08978741 0.07731366 0.06727491 0.05911289
// 0.40000 0.13253818 0.11128511 0.09459590 0.08132834 0.07066107 0.06199500
// 0.45000 0.13687208 0.11481163 0.09750361 0.08375387 0.07270534 0.06373386
// 0.50000 0.13832410 0.11599237 0.09847664 0.08456518 0.07338887 0.06431510
// 0.55000 0.13687208 0.11481163 0.09750361 0.08375387 0.07270534 0.06373386
// 0.60000 0.13253818 0.11128511 0.09459590 0.08132834 0.07066107 0.06199500
// 0.65000 0.12538832 0.10545958 0.08978741 0.07731366 0.06727491 0.05911289
// 0.70000 0.11553050 0.09741183 0.08313394 0.07175114 0.06257797 0.05511132
// 0.75000 0.10311208 0.08724696 0.07471205 0.06469760 0.05661313 0.05002313
// 0.80000 0.08831616 0.07509618 0.06461766 0.05622444 0.04943437 0.04388975
// 0.85000 0.07135702 0.06111390 0.05296419 0.04641639 0.04110601 0.03676066
// 0.90000 0.05247504 0.04547452 0.03988045 0.03537016 0.03170171 0.02869272
// 0.95000 0.03193096 0.02836880 0.02550828 0.02319280 0.02130337 0.01974941
// 1.00000 0.01000000 0.01000000 0.01000000 0.01000000 0.01000000 0.01000000
double PSParallelCompact::dead_wood_limiter(double density, size_t min_percent)
{
assert(_dwl_initialized, "uninitialized");
// The raw limit is the value of the normal distribution at x = density.
const double raw_limit = normal_distribution(density);
// Adjust the raw limit so it becomes the minimum when the density is 1.
//
// First subtract the adjustment value (which is simply the precomputed value
// normal_distribution(1.0)); this yields a value of 0 when the density is 1.
// Then add the minimum value, so the minimum is returned when the density is
// 1. Finally, prevent negative values, which occur when the mean is not 0.5.
const double min = double(min_percent) / 100.0;
const double limit = raw_limit - _dwl_adjustment + min;
return MAX2(limit, 0.0);
}
ParallelCompactData::RegionData*
PSParallelCompact::first_dead_space_region(const RegionData* beg,
const RegionData* end)
@ -1091,67 +1018,6 @@ PSParallelCompact::first_dead_space_region(const RegionData* beg,
return sd.region(left);
}
ParallelCompactData::RegionData*
PSParallelCompact::dead_wood_limit_region(const RegionData* beg,
const RegionData* end,
size_t dead_words)
{
ParallelCompactData& sd = summary_data();
size_t left = sd.region(beg);
size_t right = end > beg ? sd.region(end) - 1 : left;
// Binary search.
while (left < right) {
// Equivalent to (left + right) / 2, but does not overflow.
const size_t middle = left + (right - left) / 2;
RegionData* const middle_ptr = sd.region(middle);
HeapWord* const dest = middle_ptr->destination();
HeapWord* const addr = sd.region_to_addr(middle);
assert(dest != nullptr, "sanity");
assert(dest <= addr, "must move left");
const size_t dead_to_left = pointer_delta(addr, dest);
if (middle > left && dead_to_left > dead_words) {
right = middle - 1;
} else if (middle < right && dead_to_left < dead_words) {
left = middle + 1;
} else {
return middle_ptr;
}
}
return sd.region(left);
}
// The result is valid during the summary phase, after the initial summarization
// of each space into itself, and before final summarization.
inline double
PSParallelCompact::reclaimed_ratio(const RegionData* const cp,
HeapWord* const bottom,
HeapWord* const top,
HeapWord* const new_top)
{
ParallelCompactData& sd = summary_data();
assert(cp != nullptr, "sanity");
assert(bottom != nullptr, "sanity");
assert(top != nullptr, "sanity");
assert(new_top != nullptr, "sanity");
assert(top >= new_top, "summary data problem?");
assert(new_top > bottom, "space is empty; should not be here");
assert(new_top >= cp->destination(), "sanity");
assert(top >= sd.region_to_addr(cp), "sanity");
HeapWord* const destination = cp->destination();
const size_t dense_prefix_live = pointer_delta(destination, bottom);
const size_t compacted_region_live = pointer_delta(new_top, destination);
const size_t compacted_region_used = pointer_delta(top,
sd.region_to_addr(cp));
const size_t reclaimable = compacted_region_used - compacted_region_live;
const double divisor = dense_prefix_live + 1.25 * compacted_region_live;
return double(reclaimable) / divisor;
}
// Return the address of the end of the dense prefix, a.k.a. the start of the
// compacted region. The address is always on a region boundary.
//
@ -1201,45 +1067,29 @@ PSParallelCompact::compute_dense_prefix(const SpaceId id,
return sd.region_to_addr(full_cp);
}
const size_t space_live = pointer_delta(new_top, bottom);
const size_t space_used = space->used_in_words();
const size_t space_capacity = space->capacity_in_words();
// Iteration starts with the region *after* the full-region-prefix-end.
const RegionData* const start_region = full_cp;
// If final region is not full, iteration stops before that region,
// because fill_dense_prefix_end assumes that prefix_end <= top.
const RegionData* const end_region = sd.addr_to_region_ptr(space->top());
assert(start_region <= end_region, "inv");
const double density = double(space_live) / double(space_capacity);
const size_t min_percent_free = MarkSweepDeadRatio;
const double limiter = dead_wood_limiter(density, min_percent_free);
const size_t dead_wood_max = space_used - space_live;
const size_t dead_wood_limit = MIN2(size_t(space_capacity * limiter),
dead_wood_max);
log_develop_debug(gc, compaction)(
"space_live=" SIZE_FORMAT " space_used=" SIZE_FORMAT " "
"space_cap=" SIZE_FORMAT,
space_live, space_used,
space_capacity);
log_develop_debug(gc, compaction)(
"dead_wood_limiter(%6.4f, " SIZE_FORMAT ")=%6.4f "
"dead_wood_max=" SIZE_FORMAT " dead_wood_limit=" SIZE_FORMAT,
density, min_percent_free, limiter,
dead_wood_max, dead_wood_limit);
// Locate the region with the desired amount of dead space to the left.
const RegionData* const limit_cp =
dead_wood_limit_region(full_cp, top_cp, dead_wood_limit);
// Scan from the first region with dead space to the limit region and find the
// one with the best (largest) reclaimed ratio.
double best_ratio = 0.0;
const RegionData* best_cp = full_cp;
for (const RegionData* cp = full_cp; cp < limit_cp; ++cp) {
double tmp_ratio = reclaimed_ratio(cp, bottom, top, new_top);
if (tmp_ratio > best_ratio) {
best_cp = cp;
best_ratio = tmp_ratio;
size_t max_waste = space->capacity_in_words() * (MarkSweepDeadRatio / 100.0);
const RegionData* cur_region = start_region;
for (/* empty */; cur_region < end_region; ++cur_region) {
assert(region_size >= cur_region->data_size(), "inv");
size_t dead_size = region_size - cur_region->data_size();
if (max_waste < dead_size) {
break;
}
max_waste -= dead_size;
}
return sd.region_to_addr(best_cp);
HeapWord* const prefix_end = sd.region_to_addr(cur_region);
assert(sd.is_region_aligned(prefix_end), "postcondition");
assert(prefix_end >= sd.region_to_addr(full_cp), "in-range");
assert(prefix_end <= space->top(), "in-range");
return prefix_end;
}
void PSParallelCompact::summarize_spaces_quick()

View File

@ -922,15 +922,6 @@ class PSParallelCompact : AllStatic {
static SpanSubjectToDiscoveryClosure _span_based_discoverer;
static ReferenceProcessor* _ref_processor;
// Values computed at initialization and used by dead_wood_limiter().
static double _dwl_mean;
static double _dwl_std_dev;
static double _dwl_first_term;
static double _dwl_adjustment;
#ifdef ASSERT
static bool _dwl_initialized;
#endif // #ifdef ASSERT
public:
static ParallelOldTracer* gc_tracer() { return &_gc_tracer; }
@ -949,41 +940,11 @@ class PSParallelCompact : AllStatic {
// Methods used to compute the dense prefix.
// Compute the value of the normal distribution at x = density. The mean and
// standard deviation are values saved by initialize_dead_wood_limiter().
static inline double normal_distribution(double density);
// Initialize the static vars used by dead_wood_limiter().
static void initialize_dead_wood_limiter();
// Return the percentage of space that can be treated as "dead wood" (i.e.,
// not reclaimed).
static double dead_wood_limiter(double density, size_t min_percent);
// Find the first (left-most) region in the range [beg, end) that has at least
// dead_words of dead space to the left. The argument beg must be the first
// region in the space that is not completely live.
static RegionData* dead_wood_limit_region(const RegionData* beg,
const RegionData* end,
size_t dead_words);
// Return a pointer to the first region in the range [beg, end) that is not
// completely full.
static RegionData* first_dead_space_region(const RegionData* beg,
const RegionData* end);
// Return a value indicating the benefit or 'yield' if the compacted region
// were to start (or equivalently if the dense prefix were to end) at the
// candidate region. Higher values are better.
//
// The value is based on the amount of space reclaimed vs. the costs of (a)
// updating references in the dense prefix plus (b) copying objects and
// updating references in the compacted region.
static inline double reclaimed_ratio(const RegionData* const candidate,
HeapWord* const bottom,
HeapWord* const top,
HeapWord* const new_top);
// Compute the dense prefix for the designated space.
static HeapWord* compute_dense_prefix(const SpaceId id,
bool maximum_compaction);

View File

@ -40,12 +40,6 @@ inline bool PSParallelCompact::is_marked(oop obj) {
return mark_bitmap()->is_marked(obj);
}
inline double PSParallelCompact::normal_distribution(double density) {
assert(_dwl_initialized, "uninitialized");
const double squared_term = (density - _dwl_mean) / _dwl_std_dev;
return _dwl_first_term * exp(-0.5 * squared_term * squared_term);
}
inline bool PSParallelCompact::is_in(HeapWord* p, HeapWord* beg_addr, HeapWord* end_addr) {
return p >= beg_addr && p < end_addr;
}

View File

@ -617,12 +617,11 @@
\
product(uint, MarkSweepDeadRatio, 5, \
"Percentage (0-100) of the old gen allowed as dead wood. " \
"Serial mark sweep treats this as both the minimum and maximum " \
"Serial full gc treats this as both the minimum and maximum " \
"value. " \
"Par compact uses a variable scale based on the density of the " \
"generation and treats this as the maximum value when the heap " \
"is either completely full or completely empty. Par compact " \
"also has a smaller default value; see arguments.cpp. " \
"Parallel full gc treats this as maximum value, i.e. when " \
"allowing dead wood, Parallel full gc wastes at most this amount "\
"of space." \
"G1 full gc treats this as an allowed garbage threshold to skip " \
"compaction of heap regions, i.e. if a heap region has less " \
"garbage than this value, then the region will not be compacted" \

View File

@ -530,6 +530,9 @@ static SpecialFlag const special_jvm_flags[] = {
{ "GCLockerEdenExpansionPercent", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) },
{ "NUMAPageScanRate", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) },
{ "ProcessDistributionStride", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) },
{ "ParallelOldDeadWoodLimiterMean", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) },
{ "ParallelOldDeadWoodLimiterStdDev", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) },
#ifdef ASSERT
{ "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() },
#endif