1 /* 2 * Copyright (c) 2015, 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.plab.lib; 24 25 import java.util.ArrayList; 26 import java.util.HashMap; 27 import java.util.List; 28 import java.util.Map; 29 import java.util.Scanner; 30 import java.util.regex.Matcher; 31 import java.util.regex.Pattern; 32 import jdk.test.lib.Pair; 33 34 /** 35 * LogParser class parses VM output to get PLAB and ConsumptionStats values. 36 * 37 * Typical GC log with PLAB statistics looks like: 38 * 39 * #1: [GC pause (WhiteBox Initiated Young GC) (young) (allocated = 0 wasted = 0 unused = 0 used = 0 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) 40 * (allocated = 70692 wasted = 1450 unused = 1287 used = 67955 undo_waste = 0 region_end_waste = 0 regions filled = 1 direct_allocated = 19003 failure_used = 0 failure_waste = 0) (plab_sz = 13591 desired_plab_sz = 10193) 41 * where first line is statistic for young PLAB and second line is for old PLAB. 42 */ 43 final public class LogParser { 44 45 // Name for GC ID field in report. 46 public final static String GC_ID = "gc_id"; 47 48 /** 49 * Type of parsed log element. 50 */ 51 public static enum ReportType { 52 53 SURVIVOR_STATS, 54 OLD_STATS 55 } 56 57 private final String log; 58 private final List<Pair<ReportType, ? extends Map<String, Long>>> reportHolder; 59 60 // GC ID 61 private static final Pattern GC_ID_PATTERN = Pattern.compile("#(\\d+):"); 62 // Pattern for extraction pair <name>=<numeric value> 63 private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s*=\\s*\\d+"); 64 65 /** 66 * Construct LogParser Object 67 * 68 * @param log - VM Output 69 */ 70 public LogParser(String log) { 71 if (log == null) { 72 throw new IllegalArgumentException("Parameter log should not be null."); 73 } 74 this.log = log; 75 reportHolder = parseLines(); 76 } 77 78 /** 79 * @return log which is being processed 80 */ 81 public String getLog() { 82 return log; 83 } 84 85 /** 86 * Returns list of log entries. 87 * 88 * @return list of Pair with ReportType and Map of parameters/values. 89 */ 90 public List<Pair<ReportType, ? extends Map<String, Long>>> getEntries() { 91 return reportHolder; 92 } 93 94 private List<Pair<ReportType, ? extends Map<String, Long>>> parseLines() throws NumberFormatException { 95 Scanner lineScanner = new Scanner(log); 96 List<Pair<ReportType, ? extends Map<String, Long>>> allocationStatistics = new ArrayList<>(); 97 long gc_id = 0; 98 while (lineScanner.hasNextLine()) { 99 String line = lineScanner.nextLine(); 100 // If no any prefix - this is the Old PLAB statistics 101 ReportType currentStats = ReportType.OLD_STATS; 102 // #NUMBER - this is first line of PLAB statistics 103 if (line.startsWith("#")) { 104 currentStats = ReportType.SURVIVOR_STATS; 105 gc_id = getGcId(line); 106 } 107 108 Matcher matcher = PAIRS_PATTERN.matcher(line); 109 if (matcher.find()) { 110 HashMap<String, Long> map = new HashMap<>(); 111 map.put(GC_ID, gc_id); 112 allocationStatistics.add(new Pair<>(currentStats, map)); 113 // Extract all pairs from log. 114 do { 115 String pair = matcher.group(); 116 String[] nameValue = pair.replaceAll(" ", "").split("="); 117 map.put(nameValue[0], Long.parseLong(nameValue[1])); 118 } while (matcher.find()); 119 } 120 } 121 return allocationStatistics; 122 } 123 124 private long getGcId(String line) { 125 Matcher number = GC_ID_PATTERN.matcher(line); 126 if (number.find()) { 127 return Long.parseLong(number.group(1)); 128 } 129 throw new RuntimeException("Should not reach"); 130 } 131 }