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 } | 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.plab.lib; 24 25 import java.util.EnumMap; 26 import java.util.HashMap; 27 import java.util.Map; 28 import java.util.Optional; 29 import java.util.Scanner; 30 import java.util.regex.Matcher; 31 import java.util.regex.Pattern; 32 33 /** 34 * LogParser class parses VM output to get PLAB and ConsumptionStats values. 35 * 36 * Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like: 37 * 38 * [2,244s][info ][gc ] GC(30) Concurrent Mark abort 39 * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 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 * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 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) 41 * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms 42 * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 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) 43 * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 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) 44 * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms 45 46 */ 47 final public class LogParser { 48 49 // Name for GC ID field in report. 50 public final static String GC_ID = "gc_id"; 51 52 /** 53 * Type of parsed log element. 54 */ 55 public static enum ReportType { 56 57 SURVIVOR_STATS, 58 OLD_STATS 59 } 60 61 private final String log; 62 63 private final Map<Long, Map<ReportType, Map<String,Long>>> reportHolder; 64 65 // GC ID 66 private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\] GC\\((\\d+)\\)"); 67 // Pattern for extraction pair <name>=<numeric value> 68 private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+"); 69 70 /** 71 * Construct LogParser Object 72 * 73 * @param log - VM Output 74 */ 75 public LogParser(String log) { 76 if (log == null) { 77 throw new IllegalArgumentException("Parameter log should not be null."); 78 } 79 this.log = log; 80 reportHolder = parseLines(); 81 } 82 83 /** 84 * @return log which is being processed 85 */ 86 public String getLog() { 87 return log; 88 } 89 90 /** 91 * Returns list of log entries. 92 * 93 * @return list of Pair with ReportType and Map of parameters/values. 94 */ 95 public Map<Long,Map<ReportType, Map<String,Long>>> getEntries() { 96 return reportHolder; 97 } 98 99 private Map<Long,Map<ReportType, Map<String,Long>>> parseLines() throws NumberFormatException { 100 Scanner lineScanner = new Scanner(log); 101 Map<Long,Map<ReportType, Map<String,Long>>> allocationStatistics = new HashMap<>(); 102 Optional<Long> gc_id; 103 while (lineScanner.hasNextLine()) { 104 String line = lineScanner.nextLine(); 105 gc_id = getGcId(line); 106 if ( gc_id.isPresent() ) { 107 Matcher matcher = PAIRS_PATTERN.matcher(line); 108 if (matcher.find()) { 109 Map<ReportType,Map<String, Long>> oneReportItem; 110 ReportType reportType; 111 // Second line in log is statistics for Old PLAB allocation 112 if ( !allocationStatistics.containsKey(gc_id.get()) ) { 113 oneReportItem = new EnumMap<>(ReportType.class); 114 reportType = ReportType.SURVIVOR_STATS; 115 allocationStatistics.put(gc_id.get(), oneReportItem); 116 } else { 117 oneReportItem = allocationStatistics.get(gc_id.get()); 118 reportType = ReportType.OLD_STATS; 119 } 120 121 // Extract all pairs from log. 122 HashMap<String, Long> plabStats = new HashMap<>(); 123 do { 124 String pair = matcher.group(); 125 String[] nameValue = pair.replaceAll(" ", "").split("="); 126 plabStats.put(nameValue[0], Long.parseLong(nameValue[1])); 127 } while (matcher.find()); 128 oneReportItem.put(reportType,plabStats); 129 } 130 } 131 } 132 return allocationStatistics; 133 } 134 135 private Optional<Long> getGcId(String line) { 136 Matcher number = GC_ID_PATTERN.matcher(line); 137 if (number.find()) { 138 return Optional.of(Long.parseLong(number.group(1))); 139 } 140 return Optional.empty(); 141 } 142 } |