1 /* 2 * Copyright (c) 2012, 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 org.graalvm.compiler.replacements; 24 25 //JaCoCo Exclude 26 27 import java.io.PrintStream; 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.List; 31 32 /** 33 * A counter that can be safely {@linkplain #inc() incremented} from within a snippet for gathering 34 * snippet specific metrics. 35 */ 36 public class SnippetCounter implements Comparable<SnippetCounter> { 37 /** 38 * A group of related counters. 39 */ 40 public static class Group { 41 42 final String name; 43 final List<SnippetCounter> counters; 44 45 public Group(String name) { 46 this.name = name; 47 this.counters = new ArrayList<>(); 48 } 49 50 @Override 51 public synchronized String toString() { 52 Collections.sort(counters); 53 54 long total = 0; 55 int maxNameLen = 0; 56 for (SnippetCounter c : counters) { 57 total += c.value; 58 maxNameLen = Math.max(c.name.length(), maxNameLen); 59 } 60 61 StringBuilder buf = new StringBuilder(String.format("Counters: %s%n", name)); 62 63 String formatString = " %" + maxNameLen + "s: %6.2f%%%," + (String.format("%,d", total).length() + 2) + "d // %s%n"; 64 for (SnippetCounter c : counters) { 65 double percent = total == 0D ? 0D : ((double) (c.value * 100)) / total; 66 buf.append(String.format(formatString, c.name, percent, c.value, c.description)); 67 } 68 buf.append(String.format(formatString, "TOTAL", 100.0D, total, "")); 69 70 return buf.toString(); 71 } 72 } 73 74 /** 75 * Sorts counters in descending order of their {@linkplain #value() values}. 76 */ 77 @Override 78 public int compareTo(SnippetCounter o) { 79 if (value > o.value) { 80 return -1; 81 } else if (o.value < value) { 82 return 1; 83 } 84 return 0; 85 } 86 87 private static final List<Group> groups = new ArrayList<>(); 88 89 private final Group group; 90 private final int index; 91 private final String name; 92 private final String description; 93 private long value; 94 95 /** 96 * Creates a counter. 97 * 98 * @param group the group to which the counter belongs. If this is null, the newly created 99 * counter is disabled and {@linkplain #inc() incrementing} is a no-op. 100 * @param name the name of the counter 101 * @param description a brief comment describing the metric represented by the counter 102 */ 103 public SnippetCounter(Group group, String name, String description) { 104 this.group = group; 105 this.name = name; 106 this.description = description; 107 if (group != null) { 108 List<SnippetCounter> counters = group.counters; 109 this.index = counters.size(); 110 counters.add(this); 111 if (index == 0) { 112 groups.add(group); 113 } 114 } else { 115 this.index = -1; 116 } 117 } 118 119 /** 120 * Increments the value of this counter. This method can only be used in a snippet on a 121 * compile-time constant {@link SnippetCounter} object. 122 */ 123 public void inc() { 124 if (group != null) { 125 SnippetCounterNode.increment(this); 126 } 127 } 128 129 /** 130 * Increments the value of this counter. This method can only be used in a snippet on a 131 * compile-time constant {@link SnippetCounter} object. 132 */ 133 public void add(int increment) { 134 if (group != null) { 135 SnippetCounterNode.add(this, increment); 136 } 137 } 138 139 /** 140 * Gets the value of this counter. 141 */ 142 public long value() { 143 return value; 144 } 145 146 @Override 147 public String toString() { 148 if (group != null) { 149 return "SnippetCounter-" + group.name + ":" + name; 150 } 151 return super.toString(); 152 } 153 154 /** 155 * Prints all the counter groups to a given stream. 156 */ 157 public static void printGroups(PrintStream out) { 158 for (Group group : groups) { 159 out.println(group); 160 } 161 } 162 }