/*
* This software is Copyright 2005,2006,2007,2008 Langdale Consultants.
* Langdale Consultants can be contacted at: http://www.langdale.com.au
*/
package au.com.langdale.util;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* Intrusive profiler.
*/
public class Profiler {
private static final double MS = 1.0e-6;
private static final int CALIBRATION_SAMPLE = 1000;
/**
* Represents a single time measurement.
*/
public static class TimeSpan {
private String name;
private long t1, t2;
/**
* Begin timing.
* @param name: designates what is being timed.
*/
public TimeSpan(String name) {
this.name = name;
spans.add(this);
t1 = t2 = System.nanoTime();
}
/**
* Stop timing and complete this mea.
*/
public void stop() {
t2 = System.nanoTime();
}
/**
* Start a new measurement, stopping the present measurement.
* @param name: designates what is being timed.
* @return: the new measurement, timing in progress
*/
public TimeSpan start(String name) {
stop();
return new TimeSpan(name);
}
/**
* @return: the measurment in ms.
*/
public double getDuration() {
return (t2 - t1)* MS;
}
@Override
public String toString() {
return name + ": " + getDuration();
}
}
private static List spans = new LinkedList();
private static TimeSpan current = null;
private static long res;
/**
* Start or restart the global timer.
* @param name
*/
public static void start(String name) {
if( current != null)
current.stop();
current = new TimeSpan(name);
}
/**
* Stop the global timer.
*/
public static void stop() {
if( current != null)
current.stop();
current = null;
}
public static MultiMap summarize() {
if( current != null)
current.stop();
MultiMap map = new MultiMap();
for (Iterator it = spans.iterator(); it.hasNext();) {
TimeSpan span = (TimeSpan) it.next();
if(span.t2 != span.t1)
map.putRaw(span.name, span);
}
spans = new LinkedList(); // reset
return map;
}
/**
* Print all completed measurements and delete all measurements.
*/
public static void print() {
MultiMap summary = summarize();
System.out.println("=====================================================");
System.out.println("Task: Total (ms), Count, Ave (ms), Min (ms), Max (ms)");
Object[] keys = summary.keySet().toArray();
Arrays.sort(keys);
for (int ix = 0; ix < keys.length; ix++) {
long total = 0, min = Long.MAX_VALUE, max = Long.MIN_VALUE;
int count = 0;
Set parts = summary.find(keys[ix]);
for (Iterator it = parts.iterator(); it.hasNext();) {
TimeSpan span = (TimeSpan) it.next();
long dur = span.t2 -span.t1;
min = dur < min? dur: min;
max = dur > max? dur: max;
total += dur;
count += 1;
}
System.out.println(
keys[ix] + ": "
+ total*MS + ", "
+ count + ", "
+ total*MS/count + ", "
+ min*MS + ", "
+ max*MS);
}
}
public static void calibrate() {
res = 0;
for(int ix = 0; ix < CALIBRATION_SAMPLE; ix++) {
long t1 = System.nanoTime();
long t2;
for(;;) {
t2 = System.nanoTime();
if(t1 !=t2)
break;
}
res += t2 - t1;
}
System.out.println("Profile resolution (ns): " + (res + 0.5)/CALIBRATION_SAMPLE );
}
}