Skip to content

Commit 63af2f4

Browse files
committed
8344414: ZGC: Another division by zero in rule_major_allocation_rate
Reviewed-by: eosterlund, stefank
1 parent 077b842 commit 63af2f4

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

src/hotspot/share/gc/z/zDirector.cpp

+20-13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "gc/z/zStat.hpp"
3434
#include "logging/log.hpp"
3535

36+
#include <limits>
37+
3638
ZDirector* ZDirector::_director;
3739

3840
constexpr double one_in_1000 = 3.290527;
@@ -453,16 +455,22 @@ static double calculate_extra_young_gc_time(const ZDirectorStats& stats) {
453455
// relocation headroom into account to avoid in-place relocation.
454456
const size_t old_used = stats._old_stats._general._used;
455457
const size_t old_live = stats._old_stats._stat_heap._live_at_mark_end;
456-
const size_t old_garbage = old_used - old_live;
458+
const double old_garbage = double(old_used - old_live);
457459

458460
const double young_gc_time = gc_time(stats._young_stats);
459461

460462
// Calculate how much memory young collections are predicted to free.
461-
const size_t reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
463+
const double reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
462464

463465
// Calculate current YC time and predicted YC time after an old collection.
464-
const double current_young_gc_time_per_bytes_freed = double(young_gc_time) / double(reclaimed_per_young_gc);
465-
const double potential_young_gc_time_per_bytes_freed = double(young_gc_time) / double(reclaimed_per_young_gc + old_garbage);
466+
const double current_young_gc_time_per_bytes_freed = young_gc_time / reclaimed_per_young_gc;
467+
const double potential_young_gc_time_per_bytes_freed = young_gc_time / (reclaimed_per_young_gc + old_garbage);
468+
469+
if (current_young_gc_time_per_bytes_freed == std::numeric_limits<double>::infinity()) {
470+
// Young collection's are not reclaiming any memory. Return infinity as a signal
471+
// to trigger an old collection, regardless of the amount of old garbage.
472+
return std::numeric_limits<double>::infinity();
473+
}
466474

467475
// Calculate extra time per young collection inflicted by *not* doing an
468476
// old collection that frees up memory in the old generation.
@@ -483,13 +491,12 @@ static bool rule_major_allocation_rate(const ZDirectorStats& stats) {
483491
const double young_gc_time = gc_time(stats._young_stats);
484492

485493
// Calculate how much memory collections are predicted to free.
486-
const size_t reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
487-
const size_t reclaimed_per_old_gc = stats._old_stats._stat_heap._reclaimed_avg;
494+
const double reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
495+
const double reclaimed_per_old_gc = stats._old_stats._stat_heap._reclaimed_avg;
488496

489497
// Calculate the GC cost for each reclaimed byte
490-
const double current_young_gc_time_per_bytes_freed = double(young_gc_time) / double(reclaimed_per_young_gc);
491-
const double current_old_gc_time_per_bytes_freed = reclaimed_per_old_gc == 0 ? std::numeric_limits<double>::infinity()
492-
: (double(old_gc_time) / double(reclaimed_per_old_gc));
498+
const double current_young_gc_time_per_bytes_freed = young_gc_time / reclaimed_per_young_gc;
499+
const double current_old_gc_time_per_bytes_freed = old_gc_time / reclaimed_per_old_gc;
493500

494501
// Calculate extra time per young collection inflicted by *not* doing an
495502
// old collection that frees up memory in the old generation.
@@ -531,10 +538,10 @@ static double calculate_young_to_old_worker_ratio(const ZDirectorStats& stats) {
531538

532539
const double young_gc_time = gc_time(stats._young_stats);
533540
const double old_gc_time = gc_time(stats._old_stats);
534-
const size_t reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
535-
const size_t reclaimed_per_old_gc = stats._old_stats._stat_heap._reclaimed_avg;
536-
const double current_young_bytes_freed_per_gc_time = double(reclaimed_per_young_gc) / double(young_gc_time);
537-
const double current_old_bytes_freed_per_gc_time = double(reclaimed_per_old_gc) / double(old_gc_time);
541+
const double reclaimed_per_young_gc = stats._young_stats._stat_heap._reclaimed_avg;
542+
const double reclaimed_per_old_gc = stats._old_stats._stat_heap._reclaimed_avg;
543+
const double current_young_bytes_freed_per_gc_time = reclaimed_per_young_gc / young_gc_time;
544+
const double current_old_bytes_freed_per_gc_time = reclaimed_per_old_gc / old_gc_time;
538545

539546
if (current_young_bytes_freed_per_gc_time == 0.0) {
540547
if (current_old_bytes_freed_per_gc_time == 0.0) {

src/hotspot/share/gc/z/zStat.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#include "utilities/debug.hpp"
4747
#include "utilities/ticks.hpp"
4848

49+
#include <limits>
50+
4951
#define ZSIZE_FMT SIZE_FORMAT "M(%.0f%%)"
5052
#define ZSIZE_ARGS_WITH_MAX(size, max) ((size) / M), (percent_of(size, max))
5153
#define ZSIZE_ARGS(size) ZSIZE_ARGS_WITH_MAX(size, ZStatHeap::max_capacity())
@@ -1849,8 +1851,9 @@ void ZStatHeap::at_relocate_end(const ZPageAllocatorStats& stats, bool record_st
18491851
}
18501852
}
18511853

1852-
size_t ZStatHeap::reclaimed_avg() {
1853-
return (size_t)_reclaimed_bytes.davg();
1854+
double ZStatHeap::reclaimed_avg() {
1855+
// Make sure the reclaimed average is greater than 0.0 to avoid division by zero.
1856+
return _reclaimed_bytes.davg() + std::numeric_limits<double>::denorm_min();
18541857
}
18551858

18561859
size_t ZStatHeap::max_capacity() {

src/hotspot/share/gc/z/zStat.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ class ZStatReferences : public AllStatic {
588588
struct ZStatHeapStats {
589589
size_t _live_at_mark_end;
590590
size_t _used_at_relocate_end;
591-
size_t _reclaimed_avg;
591+
double _reclaimed_avg;
592592
};
593593

594594
//
@@ -699,7 +699,7 @@ class ZStatHeap {
699699
size_t stalls_at_relocate_start() const;
700700
size_t stalls_at_relocate_end() const;
701701

702-
size_t reclaimed_avg();
702+
double reclaimed_avg();
703703

704704
ZStatHeapStats stats();
705705

0 commit comments

Comments
 (0)