001/* 002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.replacements; 024 025//JaCoCo Exclude 026 027import java.io.*; 028import java.util.*; 029 030/** 031 * A counter that can be safely {@linkplain #inc() incremented} from within a snippet for gathering 032 * snippet specific metrics. 033 */ 034public class SnippetCounter implements Comparable<SnippetCounter> { 035 /** 036 * A group of related counters. 037 */ 038 public static class Group { 039 040 final String name; 041 final List<SnippetCounter> counters; 042 043 public Group(String name) { 044 this.name = name; 045 this.counters = new ArrayList<>(); 046 } 047 048 @Override 049 public synchronized String toString() { 050 Collections.sort(counters); 051 052 long total = 0; 053 int maxNameLen = 0; 054 for (SnippetCounter c : counters) { 055 total += c.value; 056 maxNameLen = Math.max(c.name.length(), maxNameLen); 057 } 058 059 StringBuilder buf = new StringBuilder(String.format("Counters: %s%n", name)); 060 061 String formatString = " %" + maxNameLen + "s: %6.2f%%%," + (String.format("%,d", total).length() + 2) + "d // %s%n"; 062 for (SnippetCounter c : counters) { 063 double percent = total == 0D ? 0D : ((double) (c.value * 100)) / total; 064 buf.append(String.format(formatString, c.name, percent, c.value, c.description)); 065 } 066 buf.append(String.format(formatString, "TOTAL", 100.0D, total, "")); 067 068 return buf.toString(); 069 } 070 } 071 072 /** 073 * Sorts counters in descending order of their {@linkplain #value() values}. 074 */ 075 @Override 076 public int compareTo(SnippetCounter o) { 077 if (value > o.value) { 078 return -1; 079 } else if (o.value < value) { 080 return 1; 081 } 082 return 0; 083 } 084 085 private static final List<Group> groups = new ArrayList<>(); 086 087 private final Group group; 088 private final int index; 089 private final String name; 090 private final String description; 091 private long value; 092 093 /** 094 * Creates a counter. 095 * 096 * @param group the group to which the counter belongs. If this is null, the newly created 097 * counter is disabled and {@linkplain #inc() incrementing} is a no-op. 098 * @param name the name of the counter 099 * @param description a brief comment describing the metric represented by the counter 100 */ 101 public SnippetCounter(Group group, String name, String description) { 102 this.group = group; 103 this.name = name; 104 this.description = description; 105 if (group != null) { 106 List<SnippetCounter> counters = group.counters; 107 this.index = counters.size(); 108 counters.add(this); 109 if (index == 0) { 110 groups.add(group); 111 } 112 } else { 113 this.index = -1; 114 } 115 } 116 117 /** 118 * Increments the value of this counter. This method can only be used in a snippet on a 119 * compile-time constant {@link SnippetCounter} object. 120 */ 121 public void inc() { 122 if (group != null) { 123 SnippetCounterNode.increment(this); 124 } 125 } 126 127 /** 128 * Increments the value of this counter. This method can only be used in a snippet on a 129 * compile-time constant {@link SnippetCounter} object. 130 */ 131 public void add(int increment) { 132 if (group != null) { 133 SnippetCounterNode.add(this, increment); 134 } 135 } 136 137 /** 138 * Gets the value of this counter. 139 */ 140 public long value() { 141 return value; 142 } 143 144 @Override 145 public String toString() { 146 if (group != null) { 147 return "SnippetCounter-" + group.name + ":" + name; 148 } 149 return super.toString(); 150 } 151 152 /** 153 * Prints all the counter groups to a given stream. 154 */ 155 public static void printGroups(PrintStream out) { 156 for (Group group : groups) { 157 out.println(group); 158 } 159 } 160}