1 /* 2 * Copyright (c) 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 package gc.g1.ihop.lib; 24 25 import java.util.List; 26 import java.util.regex.Matcher; 27 import java.util.regex.Pattern; 28 import java.util.stream.Collectors; 29 import java.util.stream.Stream; 30 import jdk.test.lib.process.OutputAnalyzer; 31 32 33 /** 34 * Utility class to extract IHOP related information from the GC log. 35 * The class provides a number of static method to be used from tests. 36 */ 37 public class IhopUtils { 38 39 // Examples of GC log for IHOP: 40 // [0.402s][debug][gc,ergo,ihop] GC(9) Do not request concurrent cycle initiation (still doing mixed collections) occupancy: 66060288B allocation request: 0B threshold: 59230757B (88.26) source: end of GC 41 // [0.466s][debug][gc,ergo,ihop] GC(18) Request concurrent cycle initiation (occupancy higher than threshold) occupancy: 52428800B allocation request: 0B threshold: 0B (0.00) source: end of GC 42 43 /** 44 * Patterns are used for extracting occupancy and threshold from GC log. 45 */ 46 private final static Pattern OCCUPANCY = Pattern.compile("occupancy: (\\d+)B"); 47 private final static Pattern THRESHOLD = Pattern.compile("threshold: (\\d+)B"); 48 49 /** 50 * Messages related to concurrent cycle initiation. 51 */ 52 private final static String CYCLE_INITIATION_MESSAGE = "Request concurrent cycle initiation (occupancy higher than threshold)"; 53 private final static String CYCLE_INITIATION_MESSAGE_FALSE = "Do not request concurrent cycle initiation (still doing mixed collections)"; 54 private final static String ADAPTIVE_IHOP_PREDICTION_ACTIVE_MESSAGE = "prediction active: true"; 55 56 /** 57 * Finds strings which contains patterns for finding. 58 * 59 * @param outputAnalyzer List of string for IHOP messages extraction 60 * @param stringsToFind Strings which is checked for matching with OutputAnalyzer content 61 * @return List of strings which were matched. 62 */ 63 private static List<String> findInLog(OutputAnalyzer outputAnalyzer, String... stringsToFind) { 64 return outputAnalyzer.asLines().stream() 65 .filter(string -> { 66 return Stream.of(stringsToFind) 67 .filter(find -> string.contains(find)) 68 .findAny() 69 .isPresent(); 70 }) 71 .collect(Collectors.toList()); 72 } 73 74 /** 75 * Checks that memory occupancy is greater or equal to the threshold. 76 * This methods searches for occupancy and threshold in the GC log corresponding Conc Mark Cycle initiation 77 * and compare their values.If no CMC initiation happens, does nothing. 78 * @param outputAnalyzer OutputAnalyzer which contains GC log to be checked 79 * @throw RuntimeException If check fails 80 */ 81 public static void checkIhopLogValues(OutputAnalyzer outputAnalyzer) { 82 // Concurrent cycle was initiated but was not expected. 83 // Checks occupancy should be greater than threshold. 84 List<String> logItems = IhopUtils.getErgoMessages(outputAnalyzer); 85 logItems.stream() 86 .forEach(item -> { 87 long occupancy = IhopUtils.getLongByPattern(item, IhopUtils.OCCUPANCY); 88 long threshold = IhopUtils.getLongByPattern(item, IhopUtils.THRESHOLD); 89 if (occupancy < threshold) { 90 System.out.println(outputAnalyzer.getOutput()); 91 throw new RuntimeException("Concurrent cycle initiation is unexpected. Occupancy (" + occupancy + ") is less then threshold (" + threshold + ")"); 92 } 93 System.out.printf("Concurrent cycle was initiated with occupancy = %d and threshold = %d%n", occupancy, threshold); 94 }); 95 } 96 97 private static Long getLongByPattern(String line, Pattern pattern) { 98 Matcher number = pattern.matcher(line); 99 if (number.find()) { 100 return Long.parseLong(number.group(1)); 101 } 102 System.out.println(line); 103 throw new RuntimeException("Cannot find Long in string."); 104 } 105 106 /** 107 * Finds concurrent cycle initiation messages. 108 * @param outputAnalyzer OutputAnalyzer 109 * @return List with messages which were found. 110 */ 111 public static List<String> getErgoInitiationMessages(OutputAnalyzer outputAnalyzer) { 112 return IhopUtils.findInLog(outputAnalyzer, CYCLE_INITIATION_MESSAGE); 113 } 114 115 /** 116 * Gets IHOP ergo messages from GC log. 117 * @param outputAnalyzer 118 * @return List with found messages 119 */ 120 private static List<String> getErgoMessages(OutputAnalyzer outputAnalyzer) { 121 return IhopUtils.findInLog(outputAnalyzer, CYCLE_INITIATION_MESSAGE, CYCLE_INITIATION_MESSAGE_FALSE); 122 } 123 124 /** 125 * Checks that GC log contains expected ergonomic messages 126 * @param outputAnalyzer OutputAnalyer with GC log for checking 127 * @throws RuntimeException If no IHOP ergo messages were not found 128 */ 129 public static void checkErgoMessagesExist(OutputAnalyzer outputAnalyzer) { 130 String output = outputAnalyzer.getOutput(); 131 if (!(output.contains(CYCLE_INITIATION_MESSAGE) | output.contains(CYCLE_INITIATION_MESSAGE_FALSE))) { 132 throw new RuntimeException("Cannot find expected IHOP ergonomics messages"); 133 } 134 } 135 136 /** 137 * Checks that adaptive IHOP was activated 138 * @param outputAnalyzer OutputAnalyer with GC log for checking 139 * @throws RuntimeException If IHOP message was not found. 140 */ 141 public static void checkAdaptiveIHOPWasActivated(OutputAnalyzer outputAnalyzer) { 142 outputAnalyzer.shouldContain(ADAPTIVE_IHOP_PREDICTION_ACTIVE_MESSAGE); 143 } 144 }