Mercurial > hg > truffle
diff graal/com.oracle.max.base/src/com/sun/max/profile/Metrics.java @ 3733:e233f5660da4
Added Java files from Maxine project.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 19:59:18 +0100 |
parents | |
children | bc8527f3071c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.base/src/com/sun/max/profile/Metrics.java Sat Dec 17 19:59:18 2011 +0100 @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.max.profile; + +import java.io.*; +import java.util.*; +import java.util.Arrays; + +import com.sun.max.lang.*; +import com.sun.max.program.*; + +/** + * The {@code Metrics} class implements metrics gathering for quick and dirty + * reporting of various events in a program. + */ +public final class Metrics { + + public static boolean DISABLED; + + private Metrics() { + // do nothing. + } + + private static boolean enabled; + + public interface Metric { + void reset(); + void report(String name, PrintStream stream); + } + + /** + * This class implements a simple counter that can be both incremented and accumulated. + * + */ + public static class Counter implements Metric { + protected int count; + protected long accumulation; + + public synchronized void increment() { + count++; + } + + public synchronized void accumulate(long value) { + count++; + accumulation += value; + } + + public synchronized int getCount() { + return count; + } + + public synchronized long getAccumulation() { + return accumulation; + } + + public synchronized void reset() { + count = 0; + accumulation = 0; + } + + public synchronized void report(String name, PrintStream stream) { + if (accumulation > 0) { + final double average = accumulation / (double) count; + Metrics.report(stream, name, "total", "--", String.valueOf(accumulation), "accumulated"); + Metrics.report(stream, name, "average", "--", String.valueOf(average), "accumulated (" + count + " counted)"); + } else { + Metrics.report(stream, name, "total", "--", String.valueOf(count), "counted"); + } + } + } + + public static class Rate implements Metric { + + protected final Counter counter; + protected final Clock clock; + protected long firstTicks; + protected long lastAccumulation; + protected long lastTicks; + + public Rate(Counter counter, Clock clock) { + this.counter = counter; + this.clock = clock; + firstTicks = clock.getTicks(); + lastTicks = firstTicks; + } + + public double getRate() { + return (counter.accumulation - lastAccumulation) / (double) (clock.getTicks() - lastTicks); + } + + public double getAverageRate() { + return (counter.accumulation) / (double) (clock.getTicks() - firstTicks); + } + + public void reset() { + firstTicks = clock.getTicks(); + lastTicks = firstTicks; + lastAccumulation = 0; + } + + public void resetRate() { + lastAccumulation = counter.accumulation; + lastTicks = clock.getTicks(); + } + + public void report(String name, PrintStream stream) { + double inst = getRate(); + double avg = getAverageRate(); + if (clock.getHZ() == 0) { + Metrics.report(stream, name, "inst.", "--", String.valueOf(inst), "/ tick"); + Metrics.report(stream, name, "average", "--", String.valueOf(avg), "/ tick"); + } else { + inst = inst / clock.getHZ(); + avg = avg / clock.getHZ(); + Metrics.report(stream, name, "inst.", "--", String.valueOf(inst), "/ second"); + Metrics.report(stream, name, "average", "--", String.valueOf(avg), "/ second"); + } + } + } + + /** + * This class represents a distribution of values that have been recorded. Various + * implementations implement different approximations with different time and space + * tradeoffs. + * + */ + public static class Distribution<T> implements Metric { + + static class Counted implements Comparable<Counted> { + final int total; + final Object value; + + public Counted(Object value, int total) { + this.total = total; + this.value = value; + } + + public int compareTo(Counted o) { + if (o.total < total) { + return -1; + } else if (o.total > total) { + return 1; + } + return 0; + } + + } + + protected int total; + + public int getTotal() { + return total; + } + + public int getCount(T value) { + return -1; + } + + public void reset() { + total = 0; + } + + public Map<T, Integer> asMap() { + return Collections.emptyMap(); + } + + public void report(String name, PrintStream stream) { + stream.println(name + ": "); + final Map<T, Integer> asMap = asMap(); + final Counted[] counts = new Counted[asMap.size()]; + int i = 0; + for (Map.Entry<T, Integer> entry : asMap.entrySet()) { + counts[i++] = new Counted(entry.getKey(), entry.getValue()); + } + Arrays.sort(counts); + for (Counted counted : counts) { + stream.printf(" %-10d : %s\n", counted.total, counted.value); + } + } + } + + /** + * This method increments the count of a particular named metric, creating it if necessary. + * @param name the name of the metric to increment + */ + public static void increment(String name) { + GlobalMetrics.getCounter(name).increment(); + } + + /** + * This method increases the accumulation of a particular named metric by the given value. + * Each {@code accumulate()} call counts as a single {@code increment()} call as well. + * @param name the name of the metric to accumulate + * @param value the value to add to the current accumulation + */ + public static void accumulate(String name, int value) { + GlobalMetrics.getCounter(name).accumulate(value); + } + + public static void trace(int level) { + if (Trace.hasLevel(level)) { + GlobalMetrics.report(Trace.stream()); + } + } + + public static boolean enabled() { + return enabled; + } + + static int longestMetricName = 16; + + public static void report(PrintStream out, String metricName, String runName, String benchName, String value, String units) { + out.print("@metric "); + out.print(Strings.padLengthWithSpaces(metricName, longestMetricName + 1)); + out.print(" "); + out.print(Strings.padLengthWithSpaces(runName, 9)); + out.print(" "); + out.print(Strings.padLengthWithSpaces(benchName, 18)); + out.print(" "); + out.print(Strings.padLengthWithSpaces(20, value)); + out.print(" "); + out.print(units); + out.println(""); + } + + public static void enable(boolean enable) { + enabled = enable; + } +}