Skip to content

Instantly share code, notes, and snippets.

@aaccioly
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaccioly/10002565 to your computer and use it in GitHub Desktop.
Save aaccioly/10002565 to your computer and use it in GitHub Desktop.
Time functions benchmark
--------------------------------------------
System.nanoTime()
--------------------------------------------
Avg Time: 0.99
Max Time: 1.90
Min Time: 0.51
--------------------------------------------
System.currentTimeMillis()
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
new Date().getTime()
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
java.time.Instant.now().toEpochMilli()
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
org.joda.time.Instant.now().getMillis()
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
java.time.LocalDateTime -> MILLI_OF_DAY
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
java.time.LocalDateTime -> NANO_OF_DAY
--------------------------------------------
Avg Time: 1.00
Max Time: 1.00
Min Time: 1.00
--------------------------------------------
Joda -> LocalDateTime.now().getMillisOfDay()
--------------------------------------------
Avg Time: 1.03
Max Time: 30.00
Min Time: 1.00
/*
* Copyright (c) 2014, Anthony Accioly
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of 7RTC nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sevenrtc.dtjs;
import java.time.temporal.ChronoField;
import java.util.Date;
import java.util.LongSummaryStatistics;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.LongStream;
/**
* Benchmark to compare time measuring strategies.
*
* <p>
* Compares {@link System#nanoTime()}, {@link System#currentTimeMillis()} as
* well as several {@link java.time} and
* <a href="http://www.joda.org/joda-time/">Joda-Time</a> options.
*
* @see <a href="http://stackoverflow.com/questions/22876721">Stack Overflow
* question 22876721</a>.
*
* @author Anthony Accioly
* @version 1.0
*/
public class TimeFunctionsBenchmark {
/**
* Application entry point.
*
* @param args the program arguments.
*/
public static void main(String[] args) {
// 10000 runs of 1 millisecond
final TimeFunctionsBenchmark tfb = new TimeFunctionsBenchmark(1, 1000);
// run benchmarks
final LongSummaryStatistics nanoTime
= tfb.benchmark(System::nanoTime);
final LongSummaryStatistics timeMillis
= tfb.benchmark(System::currentTimeMillis);
final LongSummaryStatistics date
= tfb.benchmark(() -> new Date().getTime());
final LongSummaryStatistics dtInstant
= tfb.benchmark(() -> java.time.Instant.now().toEpochMilli());
final LongSummaryStatistics jdInstant
= tfb.benchmark(() -> org.joda.time.Instant.now().getMillis());
final LongSummaryStatistics dtMilliOfDay
= tfb.benchmark(() -> java.time.LocalDateTime.now()
.getLong(ChronoField.MILLI_OF_DAY));
final LongSummaryStatistics dtNanoOfDay
= tfb.benchmark(() -> java.time.LocalDateTime.now()
.getLong(ChronoField.NANO_OF_DAY));
final LongSummaryStatistics jdLocalDateTime
= tfb.benchmark(() -> (long) org.joda.time.LocalDateTime.now()
.getMillisOfDay());
// print results
tfb.print("System.nanoTime()", nanoTime, t -> t * 1e-6);
tfb.print("System.currentTimeMillis()", timeMillis);
tfb.print("new Date().getTime()", date);
tfb.print("java.time.Instant.now().toEpochMilli()", dtInstant);
tfb.print("org.joda.time.Instant.now().getMillis()", jdInstant);
tfb.print("java.time.LocalDateTime -> MILLI_OF_DAY", dtMilliOfDay);
tfb.print("java.time.LocalDateTime -> NANO_OF_DAY", dtNanoOfDay,
t -> t * 1e-6);
tfb.print("Joda -> LocalDateTime.now().getMillisOfDay()",
jdLocalDateTime);
}
/**
* The number of milliseconds to sleep.
*/
private final long milliseconds;
/**
* The number of runs for each measure.
*/
private final int numberOfRuns;
/**
* Constructs a new instance of the benchmark.
*
* @param milliseconds the number of milliseconds to sleep.
* @param numberOfRuns the number of runs for each measure.
*/
public TimeFunctionsBenchmark(long milliseconds, int numberOfRuns) {
this.milliseconds = milliseconds;
this.numberOfRuns = numberOfRuns;
}
/**
* Uses a <code>timeFunction</code> to measure elapsed time in
* <code>milliseconds</code>.
*
* <p>
* This function measures how precise a <code>timeFunction</code> is.
*
* @param timeFunction the function that supplies time.
* @return time spent in milliseconds.
*/
private long measure(Supplier<Long> timeFunction) {
try {
final long init = timeFunction.get();
Thread.sleep(milliseconds);
return timeFunction.get() - init;
} catch (InterruptedException ex) {
Logger.getLogger(TimeFunctionsBenchmark.class.getName())
.log(Level.SEVERE, null, ex);
throw new RuntimeException("Could not measure time", ex);
}
}
/**
* Benchmark of a <code>timeFunction</code>.
*
* <p>
* Run {@link #measure(java.util.function.Supplier) measures} using a
* <code>timeFunction</code> for a certain number of runs. Each run will
* sleep for a specified number of milliseconds.
*
* <p>
* The <code>timeFunction</code> is called before and after each run and the
* returned times are subtracted in order to calculate the execution time.
* Precise functions with low overhead are expected to return close
* estimations of {@link #milliseconds milliseconds}.
*
* @param timeFunction the function that supplies time.
* @return a {@link LongSummaryStatistics} of time measures.
*/
public LongSummaryStatistics benchmark(Supplier<Long> timeFunction) {
return LongStream.range(0, numberOfRuns).parallel()
.map(i -> measure(timeFunction)).summaryStatistics();
}
/**
* Print a {@link LongSummaryStatistics}.
*
* <p>
* Numbers are converted to doubles without any normalization.
*
* @param caption the caption for the summary.
* @param stats the summary of statistics.
*/
public void print(String caption, LongSummaryStatistics stats) {
print(caption, stats, t -> t);
}
/**
* Print a {@link LongSummaryStatistics} normalizing its numbers.
*
* <p>
* The <tt>normalizer</tt> function is used to convert between units and
* perform any kind of adjustments.
*
* @param caption the caption for the summary.
* @param stats the summary of statistics.
* @param normalizer the normalizer function.
*/
public void print(String caption, LongSummaryStatistics stats,
DoubleUnaryOperator normalizer) {
System.out.println("--------------------------------------------");
System.out.println(caption);
System.out.println("--------------------------------------------");
System.out.printf("Avg Time: %.2f\n", normalizer.applyAsDouble(stats
.getAverage()));
System.out.printf("Max Time: %.2f\n", normalizer.applyAsDouble(stats
.getMax()));
System.out.printf("Min Time: %.2f\n", normalizer.applyAsDouble(stats
.getMin()));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment