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    CGC
  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     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  * CGC         Number of STW events during Concurrent GC's.
  48  */
  49 package utils;
  50 
  51 import common.ToolResults;
  52 import java.lang.management.GarbageCollectorMXBean;
  53 import java.lang.management.ManagementFactory;
  54 import java.util.Arrays;
  55 import java.util.List;
  56 
  57 public class JstatGcCapacityResults extends JstatResults {
  58 
  59     public JstatGcCapacityResults(ToolResults rawResults) {
  60         super(rawResults);
  61     }
  62 
  63     /**
  64      * Checks the overall consistency of the results reported by the tool
  65      */
  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         float NGCMX = getFloatValue("NGCMX");
  74         assertThat(NGCMX >= NGCMN, "NGCMN > NGCMX (min generation capacity > max generation capacity)");
  75 
  76         float NGC = getFloatValue("NGC");
  77         assertThat(NGC >= NGCMN, "NGC < NGCMN (generation capacity < min generation capacity)");
  78         assertThat(NGC <= NGCMX, "NGC > NGCMX (generation capacity > max generation capacity)");
  79 
  80         float S0C = getFloatValue("S0C");
  81         assertThat(S0C <= NGC, "S0C > NGC (survivor space 0 capacity > new generation capacity)");
  82 
  83         float S1C = getFloatValue("S1C");
  84         assertThat(S1C <= NGC, "S1C > NGC (survivor space 1 capacity > new generation capacity)");
  85 
  86         float EC = getFloatValue("EC");
  87         assertThat(EC <= NGC, "EC > NGC (eden space capacity > new generation capacity)");
  88 
  89         // Verify relative size of NGC and S0C + S1C + EC.
  90         // The rule depends on if the tenured GC is parallel or not.
  91         // For parallell GC:     NGC >= S0C + S1C + EC
  92         // For non-parallell GC: NGC == S0C + S1C + EC
  93         boolean isTenuredParallelGC = isTenuredParallelGC();
  94         String errMsg = String.format(
  95                 "NGC %s (S0C + S1C + EC) (NGC = %.1f, S0C = %.1f, S1C = %.1f, EC = %.1f, (S0C + S1C + EC) = %.1f)",
  96                 isTenuredParallelGC ? "<" : "!=", NGC, S0C, S1C, EC, S0C + S1C + EC);
  97         if (isTenuredParallelGC) {
  98             assertThat(NGC >= S0C + S1C + EC, errMsg);
  99         } else {
 100             assertThat(checkFloatIsSum(NGC, S0C, S1C, EC), errMsg);
 101         }
 102 
 103         // Check Old Gen consistency
 104         float OGCMN = getFloatValue("OGCMN");
 105         float OGCMX = getFloatValue("OGCMX");
 106         assertThat(OGCMX >= OGCMN, "OGCMN > OGCMX (min generation capacity > max generation capacity)");
 107 
 108         float OGC = getFloatValue("OGC");
 109         assertThat(OGC >= OGCMN, "OGC < OGCMN (generation capacity < min generation capacity)");
 110         assertThat(OGC <= OGCMX, "OGC > OGCMX (generation capacity > max generation capacity)");
 111         float OC = getFloatValue("OC");
 112         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))");
 113 
 114         // Check Metaspace consistency
 115         float MCMN = getFloatValue("MCMN");
 116         float MCMX = getFloatValue("MCMX");
 117         assertThat(MCMX >= MCMN, "MCMN > MCMX (min generation capacity > max generation capacity)");
 118         float MC = getFloatValue("MC");
 119         assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
 120         assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
 121 
 122 
 123     }
 124 
 125     /**
 126      * Check if the tenured generation are currently using a parallel GC.
 127      */
 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     private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
 145 
 146     private static boolean checkFloatIsSum(float sum, float... floats) {
 147         for (float f : floats) {
 148             sum -= f;
 149         }
 150 
 151         return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
 152     }
 153 
 154     private void assertThat(boolean b, String message) {
 155         if (!b) {
 156             throw new RuntimeException(message);
 157         }
 158     }
 159 
 160 }