/* * Copyright (c) 2014, Oracle America, Inc. * 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 Oracle 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 HOLDER 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 squidpony.performance; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.openjdk.jmh.runner.options.TimeValue; import squidpony.squidmath.CrossHash; import squidpony.squidmath.LongPeriodRNG; import squidpony.squidmath.ThunderRNG; import java.util.Arrays; import java.util.concurrent.TimeUnit; /** * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureFNV avgt 3 138.403 ± 13.317 ms/op * HashBenchmark.measureFNVInt avgt 3 150.326 ± 21.640 ms/op * HashBenchmark.measureJVMInt avgt 3 15.855 ± 16.418 ms/op * HashBenchmark.measureLightning avgt 3 21.636 ± 4.122 ms/op * HashBenchmark.measureLightningInt avgt 3 20.268 ± 0.624 ms/op * HashBenchmark.measureSip avgt 3 78.582 ± 25.881 ms/op * HashBenchmark.measureSipInt avgt 3 79.385 ± 30.757 ms/op * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureFNV avgt 3 137.832 ± 14.774 ms/op * HashBenchmark.measureFNVInt avgt 3 150.722 ± 5.292 ms/op * HashBenchmark.measureJVMInt avgt 3 14.928 ± 1.250 ms/op * HashBenchmark.measureLightning avgt 3 16.862 ± 6.673 ms/op * HashBenchmark.measureLightningInt avgt 3 18.505 ± 0.817 ms/op * HashBenchmark.measureSip avgt 3 77.700 ± 6.883 ms/op * HashBenchmark.measureSipInt avgt 3 77.576 ± 2.672 ms/op * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureFNV avgt 3 137.748 ± 31.812 ms/op * HashBenchmark.measureFNVInt avgt 3 150.993 ± 19.462 ms/op * HashBenchmark.measureJVMInt avgt 3 15.003 ± 2.244 ms/op * HashBenchmark.measureLightning avgt 3 19.766 ± 3.597 ms/op * HashBenchmark.measureLightningInt avgt 3 19.550 ± 7.034 ms/op * HashBenchmark.measureSip avgt 3 78.889 ± 21.236 ms/op * HashBenchmark.measureSipInt avgt 3 77.797 ± 5.196 ms/op * HashBenchmark.measureStorm avgt 3 24.542 ± 2.893 ms/op * HashBenchmark.measureStormInt avgt 3 25.070 ± 3.274 ms/op * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureControl avgt 8 1.980 ± 0.015 ms/op * HashBenchmark.measureFNV avgt 8 136.929 ± 1.341 ms/op * HashBenchmark.measureFNVInt avgt 8 150.062 ± 1.248 ms/op * HashBenchmark.measureFalcon avgt 8 15.653 ± 0.249 ms/op * HashBenchmark.measureFalconInt avgt 8 14.999 ± 0.199 ms/op <-- This is important! * HashBenchmark.measureJVMInt avgt 8 15.030 ± 0.111 ms/op <-- Because this is the collision-prone default! * HashBenchmark.measureLightning avgt 8 19.643 ± 0.109 ms/op * HashBenchmark.measureLightningInt avgt 8 19.332 ± 0.154 ms/op * HashBenchmark.measureStorm avgt 8 24.422 ± 0.185 ms/op * HashBenchmark.measureStormInt avgt 8 25.002 ± 0.306 ms/op * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureControl avgt 8 2.080 ± 0.009 ms/op * HashBenchmark.measureFNV avgt 8 143.730 ± 0.681 ms/op * HashBenchmark.measureFNVInt avgt 8 157.785 ± 1.505 ms/op * HashBenchmark.measureFalcon avgt 8 16.066 ± 0.205 ms/op * HashBenchmark.measureFalconInt avgt 8 15.321 ± 0.107 ms/op * HashBenchmark.measureJVMInt avgt 8 15.685 ± 0.109 ms/op * HashBenchmark.measureLightning avgt 8 20.617 ± 0.091 ms/op * HashBenchmark.measureLightningInt avgt 8 20.284 ± 0.053 ms/op * HashBenchmark.measureStorm avgt 8 26.013 ± 0.139 ms/op * HashBenchmark.measureStormInt avgt 8 26.278 ± 0.061 ms/op * HashBenchmark.measureWisp avgt 8 11.796 ± 0.034 ms/op <-- This is great! 64-bit hashes are fast! * HashBenchmark.measureWispInt avgt 8 13.046 ± 0.037 ms/op <-- Trying to figure out how to quicken this. * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureControl avgt 8 2.082 ± 0.009 ms/op * HashBenchmark.measureFNV avgt 8 143.760 ± 0.523 ms/op * HashBenchmark.measureFNVInt avgt 8 157.110 ± 1.180 ms/op * HashBenchmark.measureFalcon avgt 8 17.178 ± 0.038 ms/op * HashBenchmark.measureFalconInt avgt 8 15.367 ± 0.113 ms/op * HashBenchmark.measureJVMInt avgt 8 15.696 ± 0.071 ms/op * HashBenchmark.measureLightning avgt 8 20.323 ± 0.079 ms/op * HashBenchmark.measureLightningInt avgt 8 20.304 ± 0.101 ms/op * HashBenchmark.measureStorm avgt 8 25.699 ± 0.061 ms/op * HashBenchmark.measureStormInt avgt 8 26.352 ± 0.095 ms/op * HashBenchmark.measureWisp avgt 8 12.780 ± 0.062 ms/op <-- These numbers vary a lot, and may have * HashBenchmark.measureWispInt avgt 8 13.043 ± 0.041 ms/op <-- to do with processor cache availability * * With some simple changes to the finalization of Wisp to avoid strange artifacts in visual hashing... * * Benchmark Mode Cnt Score Error Units * HashBenchmark.measureChariotInt avgt 8 23.654 ± 1.395 ms/op * HashBenchmark.measureControl avgt 8 2.295 ± 0.021 ms/op * HashBenchmark.measureFNV avgt 8 155.490 ± 1.308 ms/op * HashBenchmark.measureFNVInt avgt 8 175.354 ± 3.048 ms/op * HashBenchmark.measureFalcon avgt 8 16.321 ± 0.322 ms/op * HashBenchmark.measureFalconInt avgt 8 16.837 ± 0.135 ms/op * HashBenchmark.measureJVMInt avgt 8 17.185 ± 0.198 ms/op * HashBenchmark.measureLightning avgt 8 19.045 ± 0.191 ms/op * HashBenchmark.measureLightningInt avgt 8 19.261 ± 0.225 ms/op * HashBenchmark.measureStorm avgt 8 22.690 ± 0.290 ms/op * HashBenchmark.measureStormInt avgt 8 24.048 ± 0.182 ms/op * HashBenchmark.measureWisp avgt 8 12.761 ± 0.166 ms/op // about the same (good) speed * HashBenchmark.measureWispInt avgt 8 14.122 ± 0.190 ms/op // slightly slower, finalization step probably */ public class HashBenchmark { private static long seed = 9000; private static int iseed = 9000; public long doFNV() { final LongPeriodRNG rng = new LongPeriodRNG(seed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += CrossHash.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureFNV() throws InterruptedException { seed = 9000; doFNV(); } public long doFNVInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += CrossHash.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureFNVInt() throws InterruptedException { iseed = 9000; doFNVInt(); } public long doLightning() { final LongPeriodRNG rng = new LongPeriodRNG(seed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += CrossHash.Lightning.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureLightning() throws InterruptedException { seed = 9000; doLightning(); } public long doLightningInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += CrossHash.Lightning.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureLightningInt() throws InterruptedException { iseed = 9000; doLightningInt(); } public long doJVMInt() { final LongPeriodRNG rng = new LongPeriodRNG(seed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += Arrays.hashCode(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureJVMInt() throws InterruptedException { iseed = 9000; doJVMInt(); } /* public long doStorm() { final LongPeriodRNG rng = new LongPeriodRNG(seed); CrossHash.Storm storm = new CrossHash.Storm(); for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += storm.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureStorm() throws InterruptedException { seed = 9000; doStorm(); } public long doStormInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); CrossHash.Storm storm = new CrossHash.Storm(); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += storm.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureStormInt() throws InterruptedException { iseed = 9000; doStormInt(); } */ public long doStorm() { final LongPeriodRNG rng = new LongPeriodRNG(seed); final CrossHash.Storm storm = CrossHash.Storm.mu; for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += storm.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureStorm() throws InterruptedException { seed = 9000; doStorm(); } public long doStormInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); final CrossHash.Storm storm = CrossHash.Storm.mu; for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += storm.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureStormInt() throws InterruptedException { iseed = 9000; doStormInt(); } /* public long doChariotInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); final CrossHash.Chariot chariot = CrossHash.Chariot.mu; for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += chariot.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureChariotInt() throws InterruptedException { iseed = 9000; doChariotInt(); } */ public long doFalcon() { final LongPeriodRNG rng = new LongPeriodRNG(seed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += CrossHash.Falcon.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureFalcon() throws InterruptedException { seed = 9000; doFalcon(); } public long doFalconInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += CrossHash.Falcon.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureFalconInt() throws InterruptedException { iseed = 9000; doFalconInt(); } public long doWisp() { final LongPeriodRNG rng = new LongPeriodRNG(seed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += CrossHash.Wisp.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWisp() throws InterruptedException { seed = 9000; doWisp(); } public long doWispInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += CrossHash.Wisp.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWispInt() throws InterruptedException { iseed = 9000; doWispInt(); } /* public long doWispDouble32() { final ThunderRNG rng = new ThunderRNG(seed); double[] data = new double[16]; for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 16; j++) { data[j] = rng.nextDouble(); seed += data[j] * 1024; } seed += CrossHash.Wisp.hash(data); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWispDouble32() throws InterruptedException { seed = 9000; doWispDouble32(); } public long doWispDouble32Alt() { final ThunderRNG rng = new ThunderRNG(seed); double[] data = new double[16]; for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 16; j++) { data[j] = rng.nextDouble(); seed += data[j] * 1024; } seed += CrossHash.Wisp.hashAlt(data); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWispDouble32Alt() throws InterruptedException { seed = 9000; doWispDouble32Alt(); } public long doWispDouble64() { final ThunderRNG rng = new ThunderRNG(seed); double[] data = new double[16]; for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 16; j++) { data[j] = rng.nextDouble(); seed += data[j] * 1024; } seed += CrossHash.Wisp.hash64(data); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWispDouble64() throws InterruptedException { seed = 9000; doWispDouble64(); } public long doWispDouble64Alt() { final ThunderRNG rng = new ThunderRNG(seed); double[] data = new double[16]; for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 16; j++) { data[j] = rng.nextDouble(); seed += data[j] * 1024; } seed += CrossHash.Wisp.hash64Alt(data); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureWispDouble64Alt() throws InterruptedException { seed = 9000; doWispDouble64Alt(); } */ public long doMist() { final LongPeriodRNG rng = new LongPeriodRNG(seed); final CrossHash.Mist storm = CrossHash.Mist.mu; for (int i = 0; i < 1000000; i++) { rng.nextLong(); seed += storm.hash64(rng.state); } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureMist() throws InterruptedException { seed = 9000; doMist(); } public long doMistInt() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); final CrossHash.Mist storm = CrossHash.Mist.mu; for (int i = 0; i < 1000000; i++) { rng.nextLong(); iseed += storm.hash(rng.state); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureMistInt() throws InterruptedException { iseed = 9000; doMistInt(); } public long doControl() { final LongPeriodRNG rng = new LongPeriodRNG(iseed); for (int i = 0; i < 1000000; i++) { iseed += rng.nextLong(); } return iseed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureControl() throws InterruptedException { iseed = 9000; doControl(); } public long doControlDouble() { final ThunderRNG rng = new ThunderRNG(seed); double[] data = new double[16]; for (int i = 0; i < 1000000; i++) { for (int j = 0; j < 16; j++) { data[j] = rng.nextDouble(); seed += data[j] * 1024; } } return seed; } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void measureControlDouble() throws InterruptedException { seed = 9000; doControlDouble(); } /* * ============================== HOW TO RUN THIS TEST: ==================================== * * You are expected to see the different run modes for the same benchmark. * Note the units are different, scores are consistent with each other. * * You can run this test: * * a) Via the command line from the squidlib-performance module's root folder: * $ mvn clean install * $ java -jar target/benchmarks.jar HashBenchmark -wi 8 -i 8 -f 1 -gc true * * (we requested 8 warmup/measurement iterations, single fork) * * b) Via the Java API: * (see the JMH homepage for possible caveats when running from IDE: * http://openjdk.java.net/projects/code-tools/jmh/) */ public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(HashBenchmark.class.getSimpleName()) .timeout(TimeValue.seconds(60)) .warmupIterations(8) .measurementIterations(8) .forks(1) .build(); new Runner(opt).run(); } }