1 /*
2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. 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  * Results of running the JstatGcTool ("jstat -gccapacity <pid>")
26  *
27  * Output example:
28  * NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     YGC    FGC
29  * 41984.0 671744.0  41984.0 5248.0 5248.0  31488.0    83968.0  1343488.0    83968.0    83968.0    512.0 110592.0   4480.0      0     0
30 
31  * Output description:
32  * NGCMN   Minimum new generation capacity (KB).
33  * NGCMX   Maximum new generation capacity (KB).
34  * NGC         Current new generation capacity (KB).
35  * S0C          Current survivor space 0 capacity (KB).
36  * S1C          Current survivor space 1 capacity (KB).
37  * EC            Current eden space capacity (KB).
38  * OGCMN   Minimum old generation capacity (KB).
39  * OGCMX   Maximum old generation capacity (KB).
40  * OGC         Current old generation capacity (KB).
41  * OC            Current old space capacity (KB).
42  * MCMN    Minimum metaspace capacity (KB).
43  * MCMX    Maximum metaspace capacity (KB).
44  * MC          Current metaspace capacity (KB).
45  * YGC         Number of Young generation GC Events.
46  * FGC         Number of Full GC Events.
47  */
48 package utils;
49 
50 import common.ToolResults;
51 import java.lang.management.GarbageCollectorMXBean;
52 import java.lang.management.ManagementFactory;
53 import java.util.Arrays;
54 import java.util.List;
55 
56 public class JstatGcCapacityResults extends JstatResults {
57 
JstatGcCapacityResults(ToolResults rawResults)58     public JstatGcCapacityResults(ToolResults rawResults) {
59         super(rawResults);
60     }
61 
62     /**
63      * Checks the overall consistency of the results reported by the tool
64      */
65     @Override
assertConsistency()66     public void assertConsistency() {
67 
68         // Check exit code
69         assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
70 
71         // Check Young Gen consistency
72         float NGCMN = getFloatValue("NGCMN");
73         assertThat(NGCMN >= 0, "NGCMN < 0 (min generation capacity is negative)");
74         float NGCMX = getFloatValue("NGCMX");
75         assertThat(NGCMX >= NGCMN, "NGCMN > NGCMX (min generation capacity > max generation capacity)");
76 
77         float NGC = getFloatValue("NGC");
78         assertThat(NGC >= NGCMN, "NGC < NGCMN (generation capacity < min generation capacity)");
79         assertThat(NGC <= NGCMX, "NGC > NGCMX (generation capacity > max generation capacity)");
80 
81         float S0C = getFloatValue("S0C");
82         assertThat(S0C <= NGC, "S0C > NGC (survivor space 0 capacity > new generation capacity)");
83 
84         float S1C = getFloatValue("S1C");
85         assertThat(S1C <= NGC, "S1C > NGC (survivor space 1 capacity > new generation capacity)");
86 
87         float EC = getFloatValue("EC");
88         assertThat(EC <= NGC, "EC > NGC (eden space capacity > new generation capacity)");
89 
90         // Verify relative size of NGC and S0C + S1C + EC.
91         // The rule depends on if the tenured GC is parallel or not.
92         // For parallell GC:     NGC >= S0C + S1C + EC
93         // For non-parallell GC: NGC == S0C + S1C + EC
94         boolean isTenuredParallelGC = isTenuredParallelGC();
95         String errMsg = String.format(
96                 "NGC %s (S0C + S1C + EC) (NGC = %.1f, S0C = %.1f, S1C = %.1f, EC = %.1f, (S0C + S1C + EC) = %.1f)",
97                 isTenuredParallelGC ? "<" : "!=", NGC, S0C, S1C, EC, S0C + S1C + EC);
98         if (isTenuredParallelGC) {
99             assertThat(NGC >= S0C + S1C + EC, errMsg);
100         } else {
101             assertThat(checkFloatIsSum(NGC, S0C, S1C, EC), errMsg);
102         }
103 
104         // Check Old Gen consistency
105         float OGCMN = getFloatValue("OGCMN");
106         assertThat(OGCMN >= 0, "OGCMN < 0 (min generation capacity is negative)");
107         float OGCMX = getFloatValue("OGCMX");
108         assertThat(OGCMX >= OGCMN, "OGCMN > OGCMX (min generation capacity > max generation capacity)");
109 
110         float OGC = getFloatValue("OGC");
111         assertThat(OGC >= OGCMN, "OGC < OGCMN (generation capacity < min generation capacity)");
112         assertThat(OGC <= OGCMX, "OGC > OGCMX (generation capacity > max generation capacity)");
113         float OC = getFloatValue("OC");
114         assertThat(OC == OGC, "OC != OGC (old generation capacity != old space capacity (these values should be equal since old space is made up only from one old generation))");
115 
116         // Check Metaspace consistency
117         float MCMN = getFloatValue("MCMN");
118         float MCMX = getFloatValue("MCMX");
119         assertThat(MCMX >= MCMN, "MCMN > MCMX (min generation capacity > max generation capacity)");
120         float MC = getFloatValue("MC");
121         assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
122         assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
123     }
124 
125     /**
126      * Check if the tenured generation are currently using a parallel GC.
127      */
isTenuredParallelGC()128     protected static boolean isTenuredParallelGC() {
129         // Currently the only parallel GC for the tenured generation is PS MarkSweep.
130         List<String> parallelGCs = Arrays.asList(new String[] { "PS MarkSweep"});
131         try {
132             List<GarbageCollectorMXBean> beans = ManagementFactory.getGarbageCollectorMXBeans();
133             for (GarbageCollectorMXBean bean : beans) {
134                 if (parallelGCs.contains(bean.getName())) {
135                     return true;
136                 }
137             }
138         } catch (Exception e) {
139             e.printStackTrace();
140         }
141         return false;
142     }
143 }
144