1 /*
 2  * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
 3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  *
 5  * This code is free software; you can redistribute it and/or modify it
 6  * under the terms of the GNU General Public License version 2 only, as
 7  * published by the Free Software Foundation.
 8  *
 9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 #include "gc/shenandoah/shenandoahMetrics.hpp"
27 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
28 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
29 #include "gc/shenandoah/shenandoahFreeSet.hpp"
30 
31 ShenandoahMetricsSnapshot::ShenandoahMetricsSnapshot() {
32   _heap = ShenandoahHeap::heap();
33 }
34 
35 void ShenandoahMetricsSnapshot::snap_before() {
36   _used_before = _heap->used();
37   _if_before = _heap->free_set()->internal_fragmentation();
38   _ef_before = _heap->free_set()->external_fragmentation();
39 }
40 void ShenandoahMetricsSnapshot::snap_after() {
41   _used_after = _heap->used();
42   _if_after = _heap->free_set()->internal_fragmentation();
43   _ef_after = _heap->free_set()->external_fragmentation();
44 }
45 
46 bool ShenandoahMetricsSnapshot::is_good_progress() {
47   // Under the critical threshold?
48   size_t free_actual   = _heap->free_set()->available();
49   size_t free_expected = _heap->max_capacity() / 100 * ShenandoahCriticalFreeThreshold;
50   bool prog_free = free_actual >= free_expected;
51   log_info(gc, ergo)("%s progress for free space: " SIZE_FORMAT "%s, need " SIZE_FORMAT "%s",
52                      prog_free ? "Good" : "Bad",
53                      byte_size_in_proper_unit(free_actual),   proper_unit_for_byte_size(free_actual),
54                      byte_size_in_proper_unit(free_expected), proper_unit_for_byte_size(free_expected));
55   if (!prog_free) {
56     return false;
57   }
58 
59   // Freed up enough?
60   size_t progress_actual   = (_used_before > _used_after) ? _used_before - _used_after : 0;
61   size_t progress_expected = ShenandoahHeapRegion::region_size_bytes();
62   bool prog_used = progress_actual >= progress_expected;
63   log_info(gc, ergo)("%s progress for used space: " SIZE_FORMAT "%s, need " SIZE_FORMAT "%s",
64                      prog_used ? "Good" : "Bad",
65                      byte_size_in_proper_unit(progress_actual),   proper_unit_for_byte_size(progress_actual),
66                      byte_size_in_proper_unit(progress_expected), proper_unit_for_byte_size(progress_expected));
67   if (prog_used) {
68     return true;
69   }
70 
71   // Internal fragmentation is down?
72   double if_actual = _if_before - _if_after;
73   double if_expected = 0.01; // 1% should be enough
74   bool prog_if = if_actual >= if_expected;
75   log_info(gc, ergo)("%s progress for internal fragmentation: %.1f%%, need %.1f%%",
76                      prog_if ? "Good" : "Bad",
77                      if_actual * 100, if_expected * 100);
78   if (prog_if) {
79     return true;
80   }
81 
82   // External fragmentation is down?
83   double ef_actual = _ef_before - _ef_after;
84   double ef_expected = 0.01; // 1% should be enough
85   bool prog_ef = ef_actual >= ef_expected;
86   log_info(gc, ergo)("%s progress for external fragmentation: %.1f%%, need %.1f%%",
87                      prog_ef ? "Good" : "Bad",
88                      ef_actual * 100, ef_expected * 100);
89   if (prog_ef) {
90     return true;
91   }
92 
93   // Nothing good had happened.
94   return false;
95 }