// ////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2009, Rob Eden All Rights Reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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 for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// ////////////////////////////////////////////////////////////////////////////
package gnu.trove.benchmark;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
*
*/
public class BenchmarkRunner {
private static final BenchmarkSet MAP_PUT_SET =
new BenchmarkSet( "Map Puts", new JavaHashMapPut(), new TroveHashMapPut() );
private static final BenchmarkSet MAP_GET_SET =
new BenchmarkSet( "Map Gets", new JavaHashMapGet(), new TroveHashMapGet() );
private static final BenchmarkSet MAP_ITERATION =
new BenchmarkSet( "Map Iteration", new JavaHashMapIteration(),
new TroveHashMapIteration(), new TroveHashMapForEach() );
private static final Benchmark[] CASES = { MAP_PUT_SET, MAP_GET_SET, MAP_ITERATION };
private static final Runtime RUNTIME = Runtime.getRuntime();
public static final Integer INTEGERS[] = new Integer[ 10000 ];
private static int warmup_times = 10;
private static long warmup_settle_time = 3000;
private static long run_times = 100;
private static long case_settle_time = 20;
public static void main( String[] args ) throws Exception {
List<GarbageCollectorMXBean> collectors =
ManagementFactory.getGarbageCollectorMXBeans();
if ( collectors != null && collectors.isEmpty() ) collectors = null;
if ( collectors == null ) {
System.out.println( "No garbage collector MX beans found. " +
"Garbage collection statistics will be disabled." );
}
System.gc();
for( int i = 0; i < INTEGERS.length; i++ ) {
INTEGERS[ i ] = Integer.valueOf( i );
}
// Setup
System.out.println( "Checking for external libraries..." );
System.out.print( " Colt: " );
if ( classIsAvailable( "cern.colt.map.OpenIntObjectHashMap" ) ) {
System.out.println( " found" );
MAP_PUT_SET.addDynamic(
createBenchmark( "gnu.trove.benchmark.colt.ColtHashMapPut" ) );
MAP_GET_SET.addDynamic(
createBenchmark( "gnu.trove.benchmark.colt.ColtHashMapGet" ) );
}
else System.out.println( " not found" );
System.out.print( " Trove 2: " );
if ( classIsAvailable( "gnu.trove.TIntObjectHashMap" ) ) {
System.out.println( "found" );
MAP_PUT_SET.addDynamic(
createBenchmark( "gnu.trove.benchmark.trove2.Trove2HashMapPut" ) );
MAP_GET_SET.addDynamic(
createBenchmark( "gnu.trove.benchmark.trove2.Trove2HashMapGet" ) );
MAP_ITERATION.addDynamic(
createBenchmark( "gnu.trove.benchmark.trove2.Trove2HashMapIteration" ) );
MAP_ITERATION.addDynamic(
createBenchmark( "gnu.trove.benchmark.trove2.Trove2HashMapForEach" ) );
}
else System.out.println( "not found" );
// Run
System.out.println();
System.out.println( "Running tests..." );
System.out.println();
for( Benchmark benchmark : CASES ) {
String indent_level = "";
runBenchmark( benchmark, indent_level, collectors );
}
// Object shutdown_lock = new Object();
// synchronized ( shutdown_lock ) {
// try {
// shutdown_lock.wait();
// }
// catch ( InterruptedException e ) {
// // ignore
// }
// }
}
private static void runBenchmark( Benchmark mark, String indent_level,
List<GarbageCollectorMXBean> collectors ) {
System.out.print( indent_level );
System.out.print( mark.getName() );
System.out.print( "..." );
CollectionInfo collection_info = new CollectionInfo();
getGCTime( collectors, collection_info, null );
long total_time = 0;
if ( mark instanceof BenchmarkSet) {
System.out.println();
String child_indent = indent_level + " ";
List<Benchmark> child_cases = ( (BenchmarkSet) mark ).getCases();
for( int i = 0; i < child_cases.size(); i++ ) {
Benchmark child = child_cases.get( i );
runBenchmark( child, child_indent, collectors );
}
System.out.print( indent_level );
System.out.print( mark.getName() );
System.out.print( ": " );
}
else {
// Run a few times to warm up
for( int i = 0; i < warmup_times; i++ ) {
mark.setUp();
mark.run();
mark.tearDown();
}
// Wait for hotspot to have time to compile
sleep( warmup_settle_time );
// Run the tests
for( int i = 0; i < run_times; i++ ) {
mark.setUp();
long start_time = System.nanoTime();
mark.run();
total_time += System.nanoTime() - start_time;
mark.tearDown();
}
}
// gc_info = getGCTime( collectors, gc_info );
System.out.print( "done" );
if ( total_time == 0 ) System.out.println( "." );
else {
System.out.print( ": " );
System.out.println(
TimeUnit.MILLISECONDS.convert( total_time, TimeUnit.NANOSECONDS ) );
}
}
private static void sleep( long time ) {
try {
Thread.sleep( time );
}
catch( InterruptedException ex ) {
// ignore
}
}
private static boolean classIsAvailable( String class_name ) {
try {
Class.forName( "cern.colt.map.OpenIntObjectHashMap" );
return true;
}
catch( Throwable t ) {
return false;
}
}
private static Benchmark createBenchmark( String class_name )
throws Exception {
return (Benchmark) Class.forName( class_name ).newInstance();
}
private static CollectionInfo getGCTime( List<GarbageCollectorMXBean> collectors,
CollectionInfo fill_into, CollectionInfo since_info ) {
long count = 0;
long time = 0;
//noinspection ForLoopReplaceableByForEach
for( int i = 0; i < collectors.size(); i++ ) {
GarbageCollectorMXBean bean = collectors.get( i );
count += bean.getCollectionCount();
time += bean.getCollectionTime();
}
long free_mem = RUNTIME.freeMemory();
if ( since_info == null ) fill_into.fill( free_mem, count, time );
else fill_into.fill( free_mem, since_info, count, time );
return fill_into;
}
private static class CollectionInfo {
private long free_mem;
private long count;
private long time;
CollectionInfo() {}
void fill( long free_mem, long count, long time ) {
this.count = count;
this.time = time;
}
void fill( long free_mem, CollectionInfo start, long end_count, long end_time ) {
this.count = end_count - start.count;
this.time = end_time - start.time;
}
}
}