blob: 65f04ab4d73cf90a2b3174f1eeb89ae8af4230e2 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2011-2012, Google, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.dev.util;
import com.ibm.icu.text.DecimalFormat;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.util.ULocale;
public final class Timer {
public static final long SECONDS = 100000000;
private long startTime;
private long duration;
private boolean timing = false;
private int iterations;
private long timingPeriod = 5*SECONDS;
{
start();
}
public Timer start() {
startTime = System.nanoTime();
timing = true;
duration = Long.MIN_VALUE;
return this;
}
public long getDuration() {
if (timing) {
duration = System.nanoTime() - startTime;
timing = false;
}
return duration;
}
public long stop() {
return getDuration();
}
public int getIterations() {
return iterations;
}
public long getTimingPeriod() {
return timingPeriod;
}
public Timer setTimingPeriod(long timingPeriod) {
this.timingPeriod = timingPeriod;
return this;
}
public DecimalFormat getNumberFormat() {
return nf;
}
public DecimalFormat getPercentFormat() {
return pf;
}
public String toString() {
return nf.format(getDuration()) + "\tns";
}
public String toString(Timer other) {
return toString(1L, other.getDuration());
}
public String toString(long iterations) {
return nf.format(getDuration()/iterations) + "\tns";
}
public String toString(long iterations, long other) {
return nf.format(getDuration()/iterations) + "\tns\t" + pf.format((double)getDuration()/other - 1D) + "";
}
private DecimalFormat nf = (DecimalFormat) NumberFormat.getNumberInstance(ULocale.ENGLISH);
private DecimalFormat pf = (DecimalFormat) NumberFormat.getPercentInstance(ULocale.ENGLISH);
{
pf.setMaximumFractionDigits(1);
pf.setPositivePrefix("+");
}
public abstract static class Loop {
public void init(Object... params) {}
abstract public void time(int repeat);
}
public long timeIterations(Loop loop, Object... params) {
// Timing on Java is very tricky, especially when you count in garbage collection. This is a simple strategy for now, we might improve later.
// The current strategy is to warm up once, then time it until we reach the timingPeriod (eg 5 seconds), increasing the iterations each time
// At first, we double the iterations.
// Once we get to within 1/4 of the timingPeriod, we change to adding 33%, plus 1. We also remember the shortest duration from this point on.
// We return the shortest of the durations.
loop.init(params);
System.gc();
start();
loop.time(1);
stop();
iterations = 1;
long shortest = Long.MAX_VALUE;
while (true) {
System.gc();
start();
loop.time(iterations);
stop();
if (duration >= timingPeriod) {
duration /= iterations;
return Math.min(duration, shortest);
} else if (duration >= timingPeriod / 4) {
duration /= iterations;
shortest = Math.min(duration, shortest);
iterations = (iterations * 4) / 3 + 1;
} else {
iterations = iterations * 2;
}
}
}
}