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