1 /*
   2  * Copyright (c) 2015, 2016, 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 
  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     public void assertConsistency() {
  66 
  67         // Check exit code
  68         assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
  69 
  70         // Check Young Gen consistency
  71         float NGCMN = getFloatValue("NGCMN");
  72         float NGCMX = getFloatValue("NGCMX");
  73         assertThat(NGCMX >= NGCMN, "NGCMN > NGCMX (min generation capacity > max generation capacity)");
  74 
  75         float NGC = getFloatValue("NGC");
  76         assertThat(NGC >= NGCMN, "NGC < NGCMN (generation capacity < min generation capacity)");
  77         assertThat(NGC <= NGCMX, "NGC > NGCMX (generation capacity > max generation capacity)");
  78 
  79         float S0C = getFloatValue("S0C");
  80         assertThat(S0C <= NGC, "S0C > NGC (survivor space 0 capacity > new generation capacity)");
  81 
  82         float S1C = getFloatValue("S1C");
  83         assertThat(S1C <= NGC, "S1C > NGC (survivor space 1 capacity > new generation capacity)");
  84 
  85         float EC = getFloatValue("EC");
  86         assertThat(EC <= NGC, "EC > NGC (eden space capacity > new generation capacity)");
  87 
  88         // Verify relative size of NGC and S0C + S1C + EC.
  89         // The rule depends on if the tenured GC is parallel or not.
  90         // For parallell GC:     NGC >= S0C + S1C + EC
  91         // For non-parallell GC: NGC == S0C + S1C + EC
  92         boolean isTenuredParallelGC = isTenuredParallelGC();
  93         String errMsg = String.format(
  94                 "NGC %s (S0C + S1C + EC) (NGC = %.1f, S0C = %.1f, S1C = %.1f, EC = %.1f, (S0C + S1C + EC) = %.1f)",
  95                 isTenuredParallelGC ? "<" : "!=", NGC, S0C, S1C, EC, S0C + S1C + EC);
  96         if (isTenuredParallelGC) {
  97             assertThat(NGC >= S0C + S1C + EC, errMsg);
  98         } else {
  99             assertThat(checkFloatIsSum(NGC, S0C, S1C, EC), errMsg);
 100         }
 101 
 102         // Check Old Gen consistency
 103         float OGCMN = getFloatValue("OGCMN");
 104         float OGCMX = getFloatValue("OGCMX");
 105         assertThat(OGCMX >= OGCMN, "OGCMN > OGCMX (min generation capacity > max generation capacity)");
 106 
 107         float OGC = getFloatValue("OGC");
 108         assertThat(OGC >= OGCMN, "OGC < OGCMN (generation capacity < min generation capacity)");
 109         assertThat(OGC <= OGCMX, "OGC > OGCMX (generation capacity > max generation capacity)");
 110         float OC = getFloatValue("OC");
 111         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))");
 112 
 113         // Check Metaspace consistency
 114         float MCMN = getFloatValue("MCMN");
 115         float MCMX = getFloatValue("MCMX");
 116         assertThat(MCMX >= MCMN, "MCMN > MCMX (min generation capacity > max generation capacity)");
 117         float MC = getFloatValue("MC");
 118         assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
 119         assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
 120 
 121 
 122     }
 123 
 124     /**
 125      * Check if the tenured generation are currently using a parallel GC.
 126      */
 127     protected static boolean isTenuredParallelGC() {
 128         // Currently the only parallel GC for the tenured generation is PS MarkSweep.
 129         List<String> parallelGCs = Arrays.asList(new String[] { "PS MarkSweep"});
 130         try {
 131             List<GarbageCollectorMXBean> beans = ManagementFactory.getGarbageCollectorMXBeans();
 132             for (GarbageCollectorMXBean bean : beans) {
 133                 if (parallelGCs.contains(bean.getName())) {
 134                     return true;
 135                 }
 136             }
 137         } catch (Exception e) {
 138             e.printStackTrace();
 139         }
 140         return false;
 141     }
 142 
 143     private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
 144 
 145     private static boolean checkFloatIsSum(float sum, float... floats) {
 146         for (float f : floats) {
 147             sum -= f;
 148         }
 149 
 150         return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
 151     }
 152 
 153     private void assertThat(boolean b, String message) {
 154         if (!b) {
 155             throw new RuntimeException(message);
 156         }
 157     }
 158 
 159 }