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