From 1440b36663f61ebde1952d91b4a1f4c1a27fcefa Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Tue, 15 Dec 2009 18:54:02 -0800 Subject: Updating caliper to current SVN as of 20091215 A test A test/com A test/com/google A test/com/google/caliper A test/com/google/caliper/AllTests.java A test/com/google/caliper/examples A test/com/google/caliper/examples/ArraySortBenchmark.java A test/com/google/caliper/examples/BoxedDoubleToStringBenchmark.java A test/com/google/caliper/examples/ListIterationBenchmark.java A test/com/google/caliper/examples/IntModBenchmark.java A test/com/google/caliper/examples/CharacterBenchmark.java A test/com/google/caliper/examples/PrimitiveDoubleToStringBenchmark.java A test/com/google/caliper/examples/StringBuilderBenchmark.java A test/com/google/caliper/examples/EnumSetContainsBenchmark.java A test/com/google/caliper/examples/ExpensiveObjectsBenchmark.java A test/com/google/caliper/examples/FormatterBenchmark.java A lib A lib/junit.jar A lib/google-collect-1.0-rc4.jar A src A src/com A src/com/google A src/com/google/caliper A src/com/google/caliper/Caliper.java A src/com/google/caliper/Param.java A src/com/google/caliper/Parameter.java A src/com/google/caliper/ExecutionException.java A src/com/google/caliper/Run.java A src/com/google/caliper/SimpleBenchmark.java A src/com/google/caliper/ConfigurationException.java A src/com/google/caliper/Runner.java A src/com/google/caliper/TypeConverter.java A src/com/google/caliper/TimedRunnable.java A src/com/google/caliper/Benchmark.java A src/com/google/caliper/ConsoleReport.java A src/com/google/caliper/Result.java A caliper.ipr A core.iml A COPYING A build.xml Checked out revision 23. --- src/com/google/caliper/Benchmark.java | 26 +-- src/com/google/caliper/BenchmarkSuite.java | 35 ---- src/com/google/caliper/Caliper.java | 9 +- src/com/google/caliper/ConsoleReport.java | 28 ++-- src/com/google/caliper/DefaultBenchmarkSuite.java | 180 --------------------- src/com/google/caliper/Param.java | 2 +- src/com/google/caliper/Parameter.java | 8 +- src/com/google/caliper/Run.java | 13 +- src/com/google/caliper/Runner.java | 102 ++++-------- src/com/google/caliper/SimpleBenchmark.java | 171 ++++++++++++++++++++ src/com/google/caliper/TimedRunnable.java | 29 ++++ test/com/google/caliper/AllTests.java | 2 +- .../google/caliper/DefaultBenchmarkSuiteTest.java | 91 ----------- .../caliper/examples/ArraySortBenchmark.java | 112 +++++++++++++ .../examples/BoxedDoubleToStringBenchmark.java | 80 +++++++++ .../caliper/examples/CharacterBenchmark.java | 173 ++++++++++++++++++++ .../examples/DoubleToStringBenchmarkSuite.java | 77 --------- .../caliper/examples/EnumSetContainsBenchmark.java | 98 +++++++++++ .../examples/EnumSetContainsBenchmarkSuite.java | 103 ------------ .../examples/ExpensiveObjectsBenchmark.java | 71 ++++++++ .../caliper/examples/FormatterBenchmark.java | 77 +++++++++ .../caliper/examples/FormatterBenchmarkSuite.java | 98 ----------- .../google/caliper/examples/IntModBenchmark.java | 90 +++++++++++ .../caliper/examples/ListIterationBenchmark.java | 80 +++++++++ .../examples/ListIterationBenchmarkSuite.java | 82 ---------- .../examples/PrimitiveDoubleToStringBenchmark.java | 80 +++++++++ .../caliper/examples/SortBenchmarkSuite.java | 115 ------------- .../caliper/examples/StringBuilderBenchmark.java | 132 +++++++++++++++ 28 files changed, 1271 insertions(+), 893 deletions(-) delete mode 100644 src/com/google/caliper/BenchmarkSuite.java delete mode 100644 src/com/google/caliper/DefaultBenchmarkSuite.java create mode 100644 src/com/google/caliper/SimpleBenchmark.java create mode 100644 src/com/google/caliper/TimedRunnable.java delete mode 100644 test/com/google/caliper/DefaultBenchmarkSuiteTest.java create mode 100644 test/com/google/caliper/examples/ArraySortBenchmark.java create mode 100644 test/com/google/caliper/examples/BoxedDoubleToStringBenchmark.java create mode 100644 test/com/google/caliper/examples/CharacterBenchmark.java delete mode 100644 test/com/google/caliper/examples/DoubleToStringBenchmarkSuite.java create mode 100644 test/com/google/caliper/examples/EnumSetContainsBenchmark.java delete mode 100644 test/com/google/caliper/examples/EnumSetContainsBenchmarkSuite.java create mode 100644 test/com/google/caliper/examples/ExpensiveObjectsBenchmark.java create mode 100644 test/com/google/caliper/examples/FormatterBenchmark.java delete mode 100644 test/com/google/caliper/examples/FormatterBenchmarkSuite.java create mode 100644 test/com/google/caliper/examples/IntModBenchmark.java create mode 100644 test/com/google/caliper/examples/ListIterationBenchmark.java delete mode 100644 test/com/google/caliper/examples/ListIterationBenchmarkSuite.java create mode 100644 test/com/google/caliper/examples/PrimitiveDoubleToStringBenchmark.java delete mode 100644 test/com/google/caliper/examples/SortBenchmarkSuite.java create mode 100644 test/com/google/caliper/examples/StringBuilderBenchmark.java diff --git a/src/com/google/caliper/Benchmark.java b/src/com/google/caliper/Benchmark.java index bd60b45..19426e6 100644 --- a/src/com/google/caliper/Benchmark.java +++ b/src/com/google/caliper/Benchmark.java @@ -16,18 +16,18 @@ package com.google.caliper; -public abstract class Benchmark { +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; - /** - * Runs the benchmark through {@code trials} iterations. - * - * @return any object or null. Benchmark implementors may keep an accumulating - * value to prevent the runtime from optimizing away the code under test. - * Such an accumulator value can be returned here. - */ - public abstract Object run(int trials) throws Exception; +/** + * A collection of benchmarks that share a set of configuration parameters. + */ +public interface Benchmark { + + Set parameterNames(); + + Set parameterValues(String parameterName); - @Override public String toString() { - return getClass().getSimpleName(); - } -} + TimedRunnable createBenchmark(Map parameterValues); +} \ No newline at end of file diff --git a/src/com/google/caliper/BenchmarkSuite.java b/src/com/google/caliper/BenchmarkSuite.java deleted file mode 100644 index 40106a0..0000000 --- a/src/com/google/caliper/BenchmarkSuite.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper; - -import java.util.Map; -import java.util.Set; - -/** - * A collection of benchmarks that share a set of configuration parameters. - */ -public abstract class BenchmarkSuite { - - protected abstract Set> benchmarkClasses(); - - protected abstract Set parameterNames(); - - protected abstract Set parameterValues(String parameterName); - - protected abstract Benchmark createBenchmark( - Class benchmark, Map parameterValues); -} \ No newline at end of file diff --git a/src/com/google/caliper/Caliper.java b/src/com/google/caliper/Caliper.java index 855101e..315431f 100644 --- a/src/com/google/caliper/Caliper.java +++ b/src/com/google/caliper/Caliper.java @@ -34,13 +34,13 @@ class Caliper { this.runNanos = runMillis * 1000000; } - public double warmUp(Benchmark benchmark) throws Exception { + public double warmUp(TimedRunnable timedRunnable) throws Exception { long startNanos = System.nanoTime(); long endNanos = startNanos + warmupNanos; int trials = 0; long currentNanos; while ((currentNanos = System.nanoTime()) < endNanos) { - benchmark.run(1); + timedRunnable.run(1); trials++; } double nanosPerExecution = (currentNanos - startNanos) / trials; @@ -54,8 +54,11 @@ class Caliper { * In the run proper, we predict how extrapolate based on warmup how many * runs we're going to need, and run them all in a single batch. */ - public double run(Benchmark test, double estimatedNanosPerTrial) throws Exception { + public double run(TimedRunnable test, double estimatedNanosPerTrial) throws Exception { int trials = (int) (runNanos / estimatedNanosPerTrial); + if (trials == 0) { + trials = 1; + } long startNanos = System.nanoTime(); test.run(trials); long endNanos = System.nanoTime(); diff --git a/src/com/google/caliper/ConsoleReport.java b/src/com/google/caliper/ConsoleReport.java index 790ffe0..b367ec4 100644 --- a/src/com/google/caliper/ConsoleReport.java +++ b/src/com/google/caliper/ConsoleReport.java @@ -18,7 +18,10 @@ package com.google.caliper; import com.google.common.collect.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; /** * Prints a report containing the tested values and the corresponding @@ -36,13 +39,14 @@ import java.util.*; final class ConsoleReport { private static final int bargraphWidth = 30; - private static final String benchmarkKey = "benchmark"; private static final String vmKey = "vm"; private final List parameters; private final Result result; private final List runs; + private final double minValue; + private final double maxValue; private final double logMaxValue; private final int decimalDigits; private final double divideBy; @@ -61,15 +65,14 @@ final class ConsoleReport { Run run = entry.getKey(); double d = entry.getValue(); - minValue = minValue < d ? minValue : d; - maxValue = maxValue > d ? maxValue : d; + minValue = Math.min(minValue, d); + maxValue = Math.max(maxValue, d); for (Map.Entry parameter : run.getParameters().entrySet()) { String name = parameter.getKey(); nameToValues.put(name, parameter.getValue()); } - nameToValues.put(benchmarkKey, run.getBenchmarkClass().getSimpleName()); nameToValues.put(vmKey, run.getVm()); } @@ -109,6 +112,8 @@ final class ConsoleReport { this.parameters = new StandardDeviationOrdering().reverse().sortedCopy(parametersBuilder); this.runs = new ByParametersOrdering().sortedCopy(result.getMeasurements().keySet()); + this.minValue = minValue; + this.maxValue = maxValue; this.logMaxValue = Math.log(maxValue); int numDigitsInMin = (int) Math.ceil(Math.log10(minValue)); @@ -155,9 +160,7 @@ final class ConsoleReport { } String get(Run run) { - if (benchmarkKey.equals(name)) { - return run.getBenchmarkClass().getSimpleName(); - } else if (vmKey.equals(name)) { + if (vmKey.equals(name)) { return run.getVm(); } else { return run.getParameters().get(name); @@ -210,6 +213,7 @@ final class ConsoleReport { * Prints a table of values. */ private void printValues() { + // header for (Parameter parameter : parameters) { if (parameter.isInteresting()) { System.out.printf("%" + parameter.maxLength + "s ", parameter.name); @@ -217,6 +221,7 @@ final class ConsoleReport { } System.out.printf("%" + measurementColumnLength + "s logarithmic runtime%n", units); + // rows String numbersFormat = "%" + measurementColumnLength + "." + decimalDigits + "f %s%n"; for (Run run : runs) { for (Parameter parameter : parameters) { @@ -245,10 +250,15 @@ final class ConsoleReport { * value. */ private String bargraph(double value) { + int numLinearChars = (int) ((value / maxValue) * bargraphWidth); double logValue = Math.log(value); int numChars = (int) ((logValue / logMaxValue) * bargraphWidth); StringBuilder result = new StringBuilder(numChars); - for (int i = 0; i < numChars; i++) { + for (int i = 0; i < numLinearChars; i++) { + result.append("X"); + } + + for (int i = numLinearChars; i < numChars; i++) { result.append("|"); } return result.toString(); diff --git a/src/com/google/caliper/DefaultBenchmarkSuite.java b/src/com/google/caliper/DefaultBenchmarkSuite.java deleted file mode 100644 index 0e197f6..0000000 --- a/src/com/google/caliper/DefaultBenchmarkSuite.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Type; -import java.util.*; - -/** - * A convenience class for implementing benchmark suites in plain code. - * Implementing classes must have a no-arguments constructor. - * - *

Benchmarks

- * The benchmarks of a suite are defined by inner classes within the suite. - * These inner classes implement the {@link Benchmark} interface. They may be - * static. They are not permitted to take parameters in their constructors. - * - *

Parameters

- * Implementing classes may be configured using parameters. Each parameter is a - * property of a benchmark, plus the default values that fulfill it. Parameters - * are specified by annotated fields: - *
- *   {@literal @}Param int length;
- * 
- * The available values for a parameter are specified by another field with the - * same name plus the {@code Values} suffix. The type of this field must be an - * {@code Iterable} of the parameter's type. - *
- *   Iterable<Integer> lengthValues = Arrays.asList(10, 100, 1000, 10000);
- * 
- * Alternatively, the available values may be specified with a method. The - * method's name follows the same naming convention and returns the same type. - * Such methods may not accept parameters of their own. - *
- *   Iterable<Integer> lengthValues() {
- *     return Arrays.asList(10, 100, 1000, 10000);
- *   }
- * 
- */ -public abstract class DefaultBenchmarkSuite extends BenchmarkSuite { - - private final Map> parameters; - private final Map, BenchmarkFactory> benchmarkFactories; - - protected void setUp() throws Exception {} - - protected DefaultBenchmarkSuite() { - parameters = Parameter.forClass(getClass()); - benchmarkFactories = createBenchmarkFactories(); - - if (benchmarkFactories.isEmpty()) { - throw new ConfigurationException( - "No benchmarks defined in " + getClass().getName()); - } - } - - protected Set> benchmarkClasses() { - return benchmarkFactories.keySet(); - } - - protected Set parameterNames() { - return parameters.keySet(); - } - - protected Set parameterValues(String parameterName) { - try { - TypeConverter typeConverter = new TypeConverter(); - Parameter parameter = parameters.get(parameterName); - if (parameter == null) { - throw new IllegalArgumentException(); - } - Collection values = parameter.values(); - Type type = parameter.getType(); - Set result = new LinkedHashSet(); - for (Object value : values) { - result.add(typeConverter.toString(value, type)); - } - return result; - } catch (Exception e) { - throw new ExecutionException(e); - } - } - - protected Benchmark createBenchmark(Class benchmarkClass, - Map parameterValues) { - TypeConverter typeConverter = new TypeConverter(); - - BenchmarkFactory benchmarkFactory = benchmarkFactories.get(benchmarkClass); - if (benchmarkFactory == null) { - throw new IllegalArgumentException(); - } - - if (!parameters.keySet().equals(parameterValues.keySet())) { - throw new IllegalArgumentException("Invalid parameters specified. Expected " - + parameters.keySet() + " but was " + parameterValues.keySet()); - } - - try { - DefaultBenchmarkSuite copyOfSelf = getClass().newInstance(); - Benchmark benchmark = benchmarkFactory.create(copyOfSelf); - for (Map.Entry entry : parameterValues.entrySet()) { - Parameter parameter = parameters.get(entry.getKey()); - Object value = typeConverter.fromString(entry.getValue(), parameter.getType()); - parameter.set(copyOfSelf, value); - } - - copyOfSelf.setUp(); - return benchmark; - - } catch (Exception e) { - throw new ExecutionException(e); - } - } - - /** - * Returns a spec for each benchmark defined in the specified class. The - * returned specs have no parameter values; those must be added separately. - */ - private Map, BenchmarkFactory> createBenchmarkFactories() { - Map, BenchmarkFactory> result - = new LinkedHashMap, BenchmarkFactory>(); - for (Class c : getClass().getDeclaredClasses()) { - if (!Benchmark.class.isAssignableFrom(c) || c.isInterface()) { - continue; - } - - @SuppressWarnings("unchecked") // guarded by isAssignableFrom - Class benchmarkClass = (Class) c; - - try { - final Constructor constructor - = benchmarkClass.getDeclaredConstructor(); - constructor.setAccessible(true); - result.put(benchmarkClass, new BenchmarkFactory() { - public Benchmark create(BenchmarkSuite suite) throws Exception { - return constructor.newInstance(); - } - }); - continue; - } catch (NoSuchMethodException ignored) { - } - - try { - final Constructor constructor - = benchmarkClass.getDeclaredConstructor(getClass()); - constructor.setAccessible(true); - result.put(benchmarkClass, new BenchmarkFactory() { - public Benchmark create(BenchmarkSuite suite) throws Exception { - return constructor.newInstance(suite); - } - }); - continue; - } catch (NoSuchMethodException ignored) { - } - - throw new ConfigurationException("No usable constructor for " - + benchmarkClass.getName() + "\n Benchmarks may only use no arguments constructors."); - } - - return result; - } - - interface BenchmarkFactory { - Benchmark create(BenchmarkSuite suite) throws Exception; - } -} \ No newline at end of file diff --git a/src/com/google/caliper/Param.java b/src/com/google/caliper/Param.java index 0a9b203..28d3588 100644 --- a/src/com/google/caliper/Param.java +++ b/src/com/google/caliper/Param.java @@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotates the field accepting a parameter in a {@link DefaultBenchmarkSuite}. + * Annotates the field accepting a parameter in a {@link SimpleBenchmark}. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) diff --git a/src/com/google/caliper/Parameter.java b/src/com/google/caliper/Parameter.java index a5ab6c8..1ba77b5 100644 --- a/src/com/google/caliper/Parameter.java +++ b/src/com/google/caliper/Parameter.java @@ -20,7 +20,7 @@ import java.lang.reflect.*; import java.util.*; /** - * A parameter in a {@link DefaultBenchmarkSuite}. + * A parameter in a {@link SimpleBenchmark}. */ abstract class Parameter { @@ -33,7 +33,7 @@ abstract class Parameter { /** * Returns all properties for the given class. */ - public static Map> forClass(Class suiteClass) { + public static Map> forClass(Class suiteClass) { Map> parameters = new TreeMap>(); for (final Field field : suiteClass.getDeclaredFields()) { if (field.isAnnotationPresent(Param.class)) { @@ -46,7 +46,7 @@ abstract class Parameter { } public static Parameter forField( - Class suiteClass, final Field field) { + Class suiteClass, final Field field) { Parameter result = null; Type returnType = null; Member member = null; @@ -110,7 +110,7 @@ abstract class Parameter { /** * Sets the value of this property to the specified value for the given suite. */ - public void set(BenchmarkSuite suite, Object value) throws Exception { + public void set(Benchmark suite, Object value) throws Exception { field.set(suite, value); } diff --git a/src/com/google/caliper/Run.java b/src/com/google/caliper/Run.java index 5ab8856..a9109de 100644 --- a/src/com/google/caliper/Run.java +++ b/src/com/google/caliper/Run.java @@ -18,6 +18,7 @@ package com.google.caliper; import com.google.common.collect.ImmutableMap; +import java.lang.reflect.Method; import java.util.Map; /** @@ -26,13 +27,9 @@ import java.util.Map; final class Run { private final ImmutableMap parameters; - private final Class benchmarkClass; private final String vm; - public Run(Map parameters, - Class benchmarkClass, - String vm) { - this.benchmarkClass = benchmarkClass; + public Run(Map parameters, String vm) { this.parameters = ImmutableMap.copyOf(parameters); this.vm = vm; } @@ -41,15 +38,11 @@ final class Run { return parameters; } - public Class getBenchmarkClass() { - return benchmarkClass; - } - public String getVm() { return vm; } @Override public String toString() { - return benchmarkClass.getSimpleName() + " " + parameters; + return "Run" + parameters; } } diff --git a/src/com/google/caliper/Runner.java b/src/com/google/caliper/Runner.java index 68f26f1..72442db 100644 --- a/src/com/google/caliper/Runner.java +++ b/src/com/google/caliper/Runner.java @@ -16,10 +16,10 @@ package com.google.caliper; -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import java.io.BufferedReader; import java.io.File; @@ -35,7 +35,7 @@ import java.util.*; public final class Runner { private String suiteClassName; - private BenchmarkSuite suite; + private Benchmark suite; /** Effective parameters to run in the benchmark. */ private Multimap parameters = LinkedHashMultimap.create(); @@ -49,12 +49,6 @@ public final class Runner { */ private Multimap userParameters = LinkedHashMultimap.create(); - /** - * Benchmark class specified by the user on the command line; or null to run - * the complete set of benchmark classes. - */ - private Class userBenchmarkClass; - /** * True if each benchmark should run in process. */ @@ -75,13 +69,13 @@ public final class Runner { private void prepareSuite() { try { @SuppressWarnings("unchecked") // guarded by the if statement that follows - Class suiteClass - = (Class) Class.forName(suiteClassName); - if (!BenchmarkSuite.class.isAssignableFrom(suiteClass)) { + Class suiteClass + = (Class) Class.forName(suiteClassName); + if (!Benchmark.class.isAssignableFrom(suiteClass)) { throw new ConfigurationException(suiteClass + " is not a benchmark suite."); } - Constructor constructor = suiteClass.getDeclaredConstructor(); + Constructor constructor = suiteClass.getDeclaredConstructor(); suite = constructor.newInstance(); } catch (InvocationTargetException e) { throw new ExecutionException(e.getCause()); @@ -121,33 +115,14 @@ public final class Runner { private List createRuns() throws Exception { List builders = new ArrayList(); - // create runs for each benchmark class - Set> benchmarkClasses = (userBenchmarkClass != null) - ? ImmutableSet.>of(userBenchmarkClass) - : suite.benchmarkClasses(); - for (Class benchmarkClass : benchmarkClasses) { - RunBuilder builder = new RunBuilder(); - builder.benchmarkClass = benchmarkClass; - builders.add(builder); - } - - // multiply the runs by the number of VMs + // create runs for each VMs Set vms = userVms.isEmpty() ? defaultVms() : userVms; - Iterator vmIterator = vms.iterator(); - String firstVm = vmIterator.next(); - for (RunBuilder builder : builders) { - builder.vm = firstVm; - } - int length = builders.size(); - while (vmIterator.hasNext()) { - String alternateVm = vmIterator.next(); - for (int s = 0; s < length; s++) { - RunBuilder copy = builders.get(s).copy(); - copy.vm = alternateVm; - builders.add(copy); - } + for (String vm : vms) { + RunBuilder runBuilder = new RunBuilder(); + runBuilder.vm = vm; + builders.add(runBuilder); } for (Map.Entry> parameter : parameters.asMap().entrySet()) { @@ -164,10 +139,10 @@ public final class Runner { } // multiply the size of the specs by the number of alternate values - length = builders.size(); + int size = builders.size(); while (values.hasNext()) { String alternate = values.next(); - for (int s = 0; s < length; s++) { + for (int s = 0; s < size; s++) { RunBuilder copy = builders.get(s).copy(); copy.parameters.put(key, alternate); builders.add(copy); @@ -185,19 +160,17 @@ public final class Runner { static class RunBuilder { Map parameters = new LinkedHashMap(); - Class benchmarkClass; String vm; RunBuilder copy() { RunBuilder result = new RunBuilder(); result.parameters.putAll(parameters); - result.benchmarkClass = benchmarkClass; result.vm = vm; return result; } public Run build() { - return new Run(parameters, benchmarkClass, vm); + return new Run(parameters, vm); } } @@ -213,8 +186,6 @@ public final class Runner { command.add("--runMillis"); command.add(String.valueOf(runMillis)); command.add("--inProcess"); - command.add("--benchmark"); - command.add(run.getBenchmarkClass().getName()); for (Map.Entry entry : run.getParameters().entrySet()) { command.add("-D" + entry.getKey() + "=" + entry.getValue()); } @@ -270,6 +241,14 @@ public final class Runner { afterRun(nanosPerTrial); resultsBuilder.put(run, nanosPerTrial); } + + // blat out our progress bar + System.out.print("\r"); + for (int j = 0; j < 80; j++) { + System.out.print(" "); + } + System.out.print("\r"); + return new Result(resultsBuilder.build()); } catch (Exception e) { throw new ExecutionException(e); @@ -283,12 +262,12 @@ public final class Runner { if (runString.length() > runStringLength) { runString = runString.substring(0, runStringLength); } - System.out.printf("%2.0f%% %-" + runStringLength + "s", + System.out.printf("\r%2.0f%% %-" + runStringLength + "s", percentDone * 100, runString); } private void afterRun(double nanosPerTrial) { - System.out.printf(" %10.0fns%n", nanosPerTrial); + System.out.printf(" %10.0fns", nanosPerTrial); } private void runInProcess() { @@ -297,10 +276,9 @@ public final class Runner { for (Run run : createRuns()) { double result; - Benchmark benchmark = suite.createBenchmark( - run.getBenchmarkClass(), run.getParameters()); - double warmupNanosPerTrial = caliper.warmUp(benchmark); - result = caliper.run(benchmark, warmupNanosPerTrial); + TimedRunnable timedRunnable = suite.createBenchmark(run.getParameters()); + double warmupNanosPerTrial = caliper.warmUp(timedRunnable); + result = caliper.run(timedRunnable, warmupNanosPerTrial); double nanosPerTrial = result; System.out.println(nanosPerTrial); } @@ -309,24 +287,11 @@ public final class Runner { } } - private boolean parseArgs(String[] args) { + private boolean parseArgs(String[] args) throws Exception { for (int i = 0; i < args.length; i++) { if ("--help".equals(args[i])) { return false; - } else if ("--benchmark".equals(args[i])) { - try { - @SuppressWarnings("unchecked") // guarded immediately afterwards! - Class c = (Class) Class.forName(args[++i]); - if (!Benchmark.class.isAssignableFrom(c)) { - System.out.println("Not a benchmark class: " + c); - return false; - } - userBenchmarkClass = c; - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } else if ("--inProcess".equals(args[i])) { inProcess = true; @@ -358,9 +323,7 @@ public final class Runner { System.out.println("Too many benchmark classes!"); return false; } - suiteClassName = args[i]; - } } @@ -388,8 +351,6 @@ public final class Runner { System.out.println(" When multiple values for the same parameter are given (via"); System.out.println(" multiple --Dx=y args), all supplied values are used."); System.out.println(); - System.out.println(" --benchmark : fix a benchmark executable to the named class"); - System.out.println(); System.out.println(" --inProcess: run the benchmark in the same JVM rather than spawning"); System.out.println(" another with the same classpath. By default each benchmark is"); System.out.println(" run in a separate VM"); @@ -403,7 +364,7 @@ public final class Runner { // adding new options? don't forget to update executeForked() } - public static void main(String... args) { + public static void main(String... args) throws Exception { // TODO: cleaner error reporting Runner runner = new Runner(); if (!runner.parseArgs(args)) { runner.printUsage(); @@ -418,11 +379,10 @@ public final class Runner { } Result result = runner.runOutOfProcess(); - System.out.println(); new ConsoleReport(result).displayResults(); } - public static void main(Class suite, String... args) { + public static void main(Class suite, String... args) throws Exception { String[] argsWithSuiteName = new String[args.length + 1]; System.arraycopy(args, 0, argsWithSuiteName, 0, args.length); argsWithSuiteName[args.length] = suite.getName(); diff --git a/src/com/google/caliper/SimpleBenchmark.java b/src/com/google/caliper/SimpleBenchmark.java new file mode 100644 index 0000000..8d2d4b1 --- /dev/null +++ b/src/com/google/caliper/SimpleBenchmark.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * A convenience class for implementing benchmarks in plain code. + * Implementing classes must have a no-arguments constructor. + * + *

Benchmarks

+ * The benchmarks of a suite are defined by . They may be + * static. They are not permitted to take parameters . . .. + * + *

Parameters

+ * Implementing classes may be configured using parameters. Each parameter is a + * property of a benchmark, plus the default values that fulfill it. Parameters + * are specified by annotated fields: + *
+ *   {@literal @}Param int length;
+ * 
+ * The available values for a parameter are specified by another field with the + * same name plus the {@code Values} suffix. The type of this field must be an + * {@code Iterable} of the parameter's type. + *
+ *   Iterable<Integer> lengthValues = Arrays.asList(10, 100, 1000, 10000);
+ * 
+ * Alternatively, the available values may be specified with a method. The + * method's name follows the same naming convention and returns the same type. + * Such methods may not accept parameters of their own. + *
+ *   Iterable<Integer> lengthValues() {
+ *     return Arrays.asList(10, 100, 1000, 10000);
+ *   }
+ * 
+ */ +public abstract class SimpleBenchmark implements Benchmark { + + private static final Class[] ARGUMENT_TYPES = { int.class }; + + private final Map> parameters; + private final Map methods; + + protected SimpleBenchmark() { + parameters = Parameter.forClass(getClass()); + methods = createTimedMethods(); + + if (methods.isEmpty()) { + throw new ConfigurationException( + "No benchmarks defined in " + getClass().getName()); + } + } + + protected void setUp() throws Exception {} + + public Set parameterNames() { + return ImmutableSet.builder() + .add("benchmark") + .addAll(parameters.keySet()) + .build(); + } + + public Set parameterValues(String parameterName) { + if ("benchmark".equals(parameterName)) { + return methods.keySet(); + } + + try { + TypeConverter typeConverter = new TypeConverter(); + Parameter parameter = parameters.get(parameterName); + if (parameter == null) { + throw new IllegalArgumentException(); + } + Collection values = parameter.values(); + Type type = parameter.getType(); + + ImmutableSet.Builder result = ImmutableSet.builder(); + for (Object value : values) { + result.add(typeConverter.toString(value, type)); + } + return result.build(); + } catch (Exception e) { + throw new ExecutionException(e); + } + } + + public TimedRunnable createBenchmark(Map parameterValues) { + TypeConverter typeConverter = new TypeConverter(); + + if (!parameterNames().equals(parameterValues.keySet())) { + throw new IllegalArgumentException("Invalid parameters specified. Expected " + + parameterNames() + " but was " + parameterValues.keySet()); + } + + try { + final SimpleBenchmark copyOfSelf = getClass().newInstance(); + final Method method = methods.get(parameterValues.get("benchmark")); + + for (Map.Entry entry : parameterValues.entrySet()) { + String parameterName = entry.getKey(); + if ("benchmark".equals(parameterName)) { + continue; + } + + Parameter parameter = parameters.get(parameterName); + Object value = typeConverter.fromString(entry.getValue(), parameter.getType()); + parameter.set(copyOfSelf, value); + } + copyOfSelf.setUp(); + + return new TimedRunnable() { + public Object run(int reps) throws Exception { + return method.invoke(copyOfSelf, reps); + } + }; + + } catch (Exception e) { + throw new ExecutionException(e); + } + } + + /** + * Returns a spec for each benchmark defined in the specified class. The + * returned specs have no parameter values; those must be added separately. + */ + private Map createTimedMethods() { + ImmutableMap.Builder result = ImmutableMap.builder(); + for (final Method method : getClass().getDeclaredMethods()) { + int modifiers = method.getModifiers(); + if (!method.getName().startsWith("time")) { + continue; + } + + if (!Modifier.isPublic(modifiers) + || Modifier.isStatic(modifiers) + || Modifier.isAbstract(modifiers) + || !Arrays.equals(method.getParameterTypes(), ARGUMENT_TYPES)) { + throw new ConfigurationException("Timed methods must be public, " + + "non-static, non-abstract and take a single int parameter. " + + "But " + method + " violates these requirements."); + } + + result.put(method.getName().substring(4), method); + } + + return result.build(); + } +} \ No newline at end of file diff --git a/src/com/google/caliper/TimedRunnable.java b/src/com/google/caliper/TimedRunnable.java new file mode 100644 index 0000000..d1f9a6c --- /dev/null +++ b/src/com/google/caliper/TimedRunnable.java @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper; + +public interface TimedRunnable { + + /** + * Runs the benchmark through {@code trials} iterations. + * + * @return any object or null. Benchmark implementors may keep an accumulating + * value to prevent the runtime from optimizing away the code under test. + * Such an accumulator value can be returned here. + */ + Object run(int reps) throws Exception; +} diff --git a/test/com/google/caliper/AllTests.java b/test/com/google/caliper/AllTests.java index 55f620a..510cc0a 100644 --- a/test/com/google/caliper/AllTests.java +++ b/test/com/google/caliper/AllTests.java @@ -22,7 +22,7 @@ import junit.framework.TestSuite; public final class AllTests { public static Test suite() { TestSuite suite = new TestSuite(); - suite.addTestSuite(DefaultBenchmarkSuiteTest.class); + // tests go here :) return suite; } } diff --git a/test/com/google/caliper/DefaultBenchmarkSuiteTest.java b/test/com/google/caliper/DefaultBenchmarkSuiteTest.java deleted file mode 100644 index 232cb4c..0000000 --- a/test/com/google/caliper/DefaultBenchmarkSuiteTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; - -import junit.framework.TestCase; - -import java.util.Arrays; -import java.util.Collection; - -public class DefaultBenchmarkSuiteTest extends TestCase { - - public void testIntrospection() { - SampleBenchmarkSuite suite = new SampleBenchmarkSuite(); - assertEquals(ImmutableSet.of("a", "b"), suite.parameterNames()); - assertEquals(ImmutableSet.of("1", "2", "3"), suite.parameterValues("a")); - assertEquals(ImmutableSet.of("4"), suite.parameterValues("b")); - assertEquals(ImmutableSet.of( - SampleBenchmarkSuite.MultiplyBenchmark.class, - SampleBenchmarkSuite.DivideBenchmark.class), - suite.benchmarkClasses()); - - } - - public void testCreateBenchmark() { - SampleBenchmarkSuite originalSuite = new SampleBenchmarkSuite(); - Benchmark benchmark = originalSuite.createBenchmark( - SampleBenchmarkSuite.MultiplyBenchmark.class, - ImmutableMap.of("a", "2", "b", "4")); - - SampleBenchmarkSuite.MultiplyBenchmark multiplyBenchmark - = (SampleBenchmarkSuite.MultiplyBenchmark) benchmark; - - SampleBenchmarkSuite multiplySuite = multiplyBenchmark.suite(); - assertNotSame(originalSuite, multiplySuite); - assertEquals(2, multiplySuite.a); - assertEquals(4, multiplySuite.b); - } - - static class SampleBenchmarkSuite extends DefaultBenchmarkSuite { - @Param int a; - - private static Collection aValues = Arrays.asList(1, 2, 3); - - @Param int b; - - private static Collection bValues() { - return Arrays.asList(4); - } - - class MultiplyBenchmark extends Benchmark { - @Override public Object run(int trials) throws Exception { - int result = 0; - for (int i = 0; i < trials; i++) { - result ^= a * b; - } - return result; - } - - SampleBenchmarkSuite suite() { - return SampleBenchmarkSuite.this; - } - } - - class DivideBenchmark extends Benchmark { - @Override public Object run(int trials) throws Exception { - int result = 0; - for (int i = 0; i < trials; i++) { - result ^= a / b; - } - return result; - } - } - } -} diff --git a/test/com/google/caliper/examples/ArraySortBenchmark.java b/test/com/google/caliper/examples/ArraySortBenchmark.java new file mode 100644 index 0000000..2978fa2 --- /dev/null +++ b/test/com/google/caliper/examples/ArraySortBenchmark.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Random; + +/** + * Measures sorting on different distributions of integers. + */ +public class ArraySortBenchmark extends SimpleBenchmark { + + @Param int length; + + static Collection lengthValues = Arrays.asList(10, 100, 1000, 10000); + + @Param Distribution distribution; + + static final Collection distributionValues = EnumSet.allOf(Distribution.class); + + int[] values; + int[] copy; + + @Override protected void setUp() throws Exception { + values = distribution.create(length); + copy = new int[length]; + } + + public int timeSort(int reps) { + int dummy = 0; + for (int i = 0; i < reps; i++) { + System.arraycopy(values, 0, copy, 0, values.length); + Arrays.sort(copy); + dummy ^= copy[0]; + } + return dummy; + } + + enum Distribution { + SAWTOOTH { + @Override + int[] create(int length) { + int[] result = new int[length]; + for (int i = 0; i < length; i += 5) { + result[i] = 0; + result[i + 1] = 1; + result[i + 2] = 2; + result[i + 3] = 3; + result[i + 4] = 4; + } + return result; + } + }, + INCREASING { + @Override + int[] create(int length) { + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + result[i] = i; + } + return result; + } + }, + DECREASING { + @Override + int[] create(int length) { + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + result[i] = length - i; + } + return result; + } + }, + RANDOM { + @Override + int[] create(int length) { + Random random = new Random(); + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + result[i] = random.nextInt(); + } + return result; + } + }; + + abstract int[] create(int length); + } + + public static void main(String[] args) throws Exception { + Runner.main(ArraySortBenchmark.class, args); + } +} diff --git a/test/com/google/caliper/examples/BoxedDoubleToStringBenchmark.java b/test/com/google/caliper/examples/BoxedDoubleToStringBenchmark.java new file mode 100644 index 0000000..5e6cbfa --- /dev/null +++ b/test/com/google/caliper/examples/BoxedDoubleToStringBenchmark.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.SimpleBenchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Measures the various ways the JDK converts boxed Doubles to Strings. + */ +public class BoxedDoubleToStringBenchmark extends SimpleBenchmark { + + @Param private Double d; + + private static final Collection dValues = Arrays.asList( + Math.PI, + -0.0d, + Double.NEGATIVE_INFINITY, + Double.NaN + ); + + public int timeStringFormat(int reps) { + Double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += String.format("%f", value).length(); + } + return dummy; + } + + public int timeToString(int reps) { + Double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += value.toString().length(); + } + return dummy; + } + + public int timeStringValueOf(int reps) { + Double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += String.valueOf(value).length(); + } + return dummy; + } + + public int timeQuoteTrick(int reps) { + Double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy = ("" + value).length(); + } + return dummy; + } + + // TODO: remove this from all examples when IDE plugins are ready + public static void main(String[] args) throws Exception { + Runner.main(BoxedDoubleToStringBenchmark.class, args); + } +} diff --git a/test/com/google/caliper/examples/CharacterBenchmark.java b/test/com/google/caliper/examples/CharacterBenchmark.java new file mode 100644 index 0000000..3ffeb01 --- /dev/null +++ b/test/com/google/caliper/examples/CharacterBenchmark.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Benchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Collection; +import java.util.EnumSet; + +/** + * Tests various Character methods, intended for testing multiple + * implementations against each other. + */ +public class CharacterBenchmark extends SimpleBenchmark { + + @Param CharacterSet characterSet; + static Collection characterSetValues = EnumSet.allOf(CharacterSet.class); + + char[] values; + + @Override protected void setUp() throws Exception { + values = characterSet.chars; + } + + enum CharacterSet { + ASCII(128), + UNICODE(65536); + char[] chars; + CharacterSet(int size) { + chars = new char[size]; + for (int i = 0; i < chars.length; ++i) { + chars[i] = (char) i; + } + } + } + + public void timeDigit(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.digit(ch, 10); + } + } + } + + public void timeGetNumericValue(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.getNumericValue(ch); + } + } + } + + public void timeIsDigit(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isDigit(ch); + } + } + } + + public void timeIsIdentifierIgnorable(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isIdentifierIgnorable(ch); + } + } + } + + public void timeIsJavaIdentifierPart(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isJavaIdentifierPart(ch); + } + } + } + + public void timeIsJavaIdentifierStart(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isJavaIdentifierStart(ch); + } + } + } + + public void timeIsLetter(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isLetter(ch); + } + } + } + + public void timeIsLetterOrDigit(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isLetterOrDigit(ch); + } + } + } + + public void timeIsLowerCase(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isLowerCase(ch); + } + } + } + + public void timeIsSpaceChar(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isSpaceChar(ch); + } + } + } + + public void timeIsUpperCase(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isUpperCase(ch); + } + } + } + + public void timeIsWhitespace(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.isWhitespace(ch); + } + } + } + + public void timeIsNull(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + boolean b = (ch == ' '); + } + } + } + + public void timeToLowerCase(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.toLowerCase(ch); + } + } + } + + public void timeToUpperCase(int reps) { + for (int i = 0; i < reps; ++i) { + for (char ch = 0; ch < '}'; ++ch) { + Character.toUpperCase(ch); + } + } + } +} diff --git a/test/com/google/caliper/examples/DoubleToStringBenchmarkSuite.java b/test/com/google/caliper/examples/DoubleToStringBenchmarkSuite.java deleted file mode 100644 index a5d5234..0000000 --- a/test/com/google/caliper/examples/DoubleToStringBenchmarkSuite.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper.examples; - -import com.google.caliper.Benchmark; -import com.google.caliper.DefaultBenchmarkSuite; -import com.google.caliper.Param; -import com.google.caliper.Runner; - -import java.util.Arrays; -import java.util.Collection; - -/** - * Measures the various ways the JDK converts doubles to Strings. - */ -public class DoubleToStringBenchmarkSuite extends DefaultBenchmarkSuite { - - @Param private Double d; - - private static Collection dValues = Arrays.asList( - Math.PI, - -0.0d, - Double.NEGATIVE_INFINITY, - Double.NaN - ); - - class FormatterBenchmark extends Benchmark { - public Object run(int trials) { - Double value = d; - String result = null; - for (int i = 0; i < trials; i++) { - result = String.format("%f", value); - } - return result; - } - } - - class ToStringBenchmark extends Benchmark { - public Object run(int trials) { - Double value = d; - String result = null; - for (int i = 0; i < trials; i++) { - result = value.toString(); - } - return result; - } - } - - class ConcatenationBenchmark extends Benchmark { - public Object run(int trials) { - Double value = d; - String result = null; - for (int i = 0; i < trials; i++) { - result = "" + value; - } - return result; - } - } - - public static void main(String[] args) { - Runner.main(DoubleToStringBenchmarkSuite.class, args); - } -} diff --git a/test/com/google/caliper/examples/EnumSetContainsBenchmark.java b/test/com/google/caliper/examples/EnumSetContainsBenchmark.java new file mode 100644 index 0000000..a9f6f2f --- /dev/null +++ b/test/com/google/caliper/examples/EnumSetContainsBenchmark.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; + +/** + * Measures EnumSet#contains(). + */ +public class EnumSetContainsBenchmark extends SimpleBenchmark { + + @Param private SetMaker setMaker; + + private static final Collection setMakerValues = EnumSet.allOf(SetMaker.class); + + enum SetMaker { + ENUM_SET { + @Override Set newSet() { + return EnumSet.allOf(RegularSize.class); + } + @Override Object[] testValues() { + return new Object[] { RegularSize.E1, RegularSize.E2, RegularSize.E20, + RegularSize.E39, RegularSize.E40, "A", LargeSize.E40, null }; + } + }, + LARGE_ENUM_SET { + @Override Set newSet() { + return EnumSet.allOf(LargeSize.class); + } + @Override Object[] testValues() { + return new Object[] { LargeSize.E1, LargeSize.E63, LargeSize.E64, + LargeSize.E65, LargeSize.E140, "A", RegularSize.E40, null }; + } + }; + + abstract Set newSet(); + abstract Object[] testValues(); + } + + enum RegularSize { + E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, + E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, + E33, E34, E35, E36, E37, E38, E39, E40, + } + + enum LargeSize { + E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, + E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, + E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E47, + E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, + E63, E64, E65, E66, E67, E68, E69, E70, E71, E72, E73, E74, E75, E76, E77, + E78, E79, E80, E81, E82, E83, E84, E85, E86, E87, E88, E89, E90, E91, E92, + E93, E94, E95, E96, E97, E98, E99, E100, E101, E102, E103, E104, E105, E106, + E107, E108, E109, E110, E111, E112, E113, E114, E115, E116, E117, E118, + E119, E120, E121, E122, E123, E124, E125, E126, E127, E128, E129, E130, + E131, E132, E133, E134, E135, E136, E137, E138, E139, E140, + } + + private Set set; + private Object[] testValues; + + @Override protected void setUp() throws Exception { + this.set = setMaker.newSet(); + this.testValues = setMaker.testValues(); + } + + public int timeContains(int reps) throws Exception { + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy ^= (set.contains(testValues[i % testValues.length]) ? i : 0); + } + return dummy; + } + + public static void main(String[] args) throws Exception { + Runner.main(EnumSetContainsBenchmark.class, args); + } +} \ No newline at end of file diff --git a/test/com/google/caliper/examples/EnumSetContainsBenchmarkSuite.java b/test/com/google/caliper/examples/EnumSetContainsBenchmarkSuite.java deleted file mode 100644 index da8f0f5..0000000 --- a/test/com/google/caliper/examples/EnumSetContainsBenchmarkSuite.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper.examples; - -import com.google.caliper.Benchmark; -import com.google.caliper.DefaultBenchmarkSuite; -import com.google.caliper.Param; -import com.google.caliper.Runner; - -import java.util.Collection; -import java.util.EnumSet; -import java.util.Set; - -/** - * Measures EnumSet#contains(). - */ -public class EnumSetContainsBenchmarkSuite extends DefaultBenchmarkSuite { - - @Param private SetMaker setMaker; - - private static Collection setMakerValues = EnumSet.allOf(SetMaker.class); - - enum SetMaker { - ENUM_SET { - @Override Set newSet() { - return EnumSet.allOf(RegularSize.class); - } - @Override Object[] testValues() { - return new Object[] { RegularSize.E1, RegularSize.E2, RegularSize.E20, - RegularSize.E39, RegularSize.E40, "A", LargeSize.E40, null }; - } - }, - LARGE_ENUM_SET { - @Override Set newSet() { - return EnumSet.allOf(LargeSize.class); - } - @Override Object[] testValues() { - return new Object[] { LargeSize.E1, LargeSize.E63, LargeSize.E64, - LargeSize.E65, LargeSize.E140, "A", RegularSize.E40, null }; - } - }; - - abstract Set newSet(); - abstract Object[] testValues(); - } - - enum RegularSize { - E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, - E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, - E33, E34, E35, E36, E37, E38, E39, E40, - } - - enum LargeSize { - E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, - E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, - E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E47, - E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, - E63, E64, E65, E66, E67, E68, E69, E70, E71, E72, E73, E74, E75, E76, E77, - E78, E79, E80, E81, E82, E83, E84, E85, E86, E87, E88, E89, E90, E91, E92, - E93, E94, E95, E96, E97, E98, E99, E100, E101, E102, E103, E104, E105, E106, - E107, E108, E109, E110, E111, E112, E113, E114, E115, E116, E117, E118, - E119, E120, E121, E122, E123, E124, E125, E126, E127, E128, E129, E130, - E131, E132, E133, E134, E135, E136, E137, E138, E139, E140, - } - - private Set set; - private Object[] testValues; - - @Override protected void setUp() throws Exception { - this.set = setMaker.newSet(); - this.testValues = setMaker.testValues(); - } - - class ContainsBenchmark extends Benchmark { - @Override public Object run(int trials) throws Exception { - int count = 0; - for (int i = 0; i < trials; i++) { - for (Object value : testValues) { - count ^= (set.contains(value) ? i : 0); - } - } - return count > 0; - } - } - - public static void main(String[] args) { - Runner.main(EnumSetContainsBenchmarkSuite.class, args); - } -} \ No newline at end of file diff --git a/test/com/google/caliper/examples/ExpensiveObjectsBenchmark.java b/test/com/google/caliper/examples/ExpensiveObjectsBenchmark.java new file mode 100644 index 0000000..2dbcf58 --- /dev/null +++ b/test/com/google/caliper/examples/ExpensiveObjectsBenchmark.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Benchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Locale; + +/** + * Benchmarks creation and cloning various expensive objects. + */ +public class ExpensiveObjectsBenchmark extends SimpleBenchmark { + public void timeNewDecimalFormatSymbols(int reps) { + for (int i = 0; i < reps; ++i) { + new DecimalFormatSymbols(Locale.US); + } + } + + public void timeClonedDecimalFormatSymbols(int reps) { + DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); + for (int i = 0; i < reps; ++i) { + dfs.clone(); + } + } + + public void timeNewNumberFormat(int reps) { + for (int i = 0; i < reps; ++i) { + NumberFormat.getInstance(Locale.US); + } + } + + public void timeClonedNumberFormat(int reps) { + NumberFormat nf = NumberFormat.getInstance(Locale.US); + for (int i = 0; i < reps; ++i) { + nf.clone(); + } + } + + public void timeNewSimpleDateFormat(int reps) { + for (int i = 0; i < reps; ++i) { + new SimpleDateFormat(); + } + } + + public void timeClonedSimpleDateFormat(int reps) { + SimpleDateFormat sdf = new SimpleDateFormat(); + for (int i = 0; i < reps; ++i) { + sdf.clone(); + } + } +} diff --git a/test/com/google/caliper/examples/FormatterBenchmark.java b/test/com/google/caliper/examples/FormatterBenchmark.java new file mode 100644 index 0000000..f61f111 --- /dev/null +++ b/test/com/google/caliper/examples/FormatterBenchmark.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Formatter; + +/** + * Compares Formatter against hand-written StringBuilder code. + */ +public class FormatterBenchmark extends SimpleBenchmark { + public void timeFormatter_NoFormatting(int reps) { + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that doesn't actually need any formatting"); + } + } + + public void timeStringBuilder_NoFormatting(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that doesn't actually need any formatting"); + } + } + + public void timeFormatter_OneInt(int reps) { + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has an int %d in it", i); + } + } + + public void timeStringBuilder_OneInt(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has an int "); + sb.append(i); + sb.append(" in it"); + } + } + + public void timeFormatter_OneString(int reps) { + for (int i = 0; i < reps; i++) { + Formatter f = new Formatter(); + f.format("this is a reasonably short string that has a string %s in it", "hello"); + } + } + + public void timeStringBuilder_OneString(int reps) { + for (int i = 0; i < reps; i++) { + StringBuilder sb = new StringBuilder(); + sb.append("this is a reasonably short string that has a string "); + sb.append("hello"); + sb.append(" in it"); + } + } + + public static void main(String[] args) throws Exception { + Runner.main(FormatterBenchmark.class, args); + } +} diff --git a/test/com/google/caliper/examples/FormatterBenchmarkSuite.java b/test/com/google/caliper/examples/FormatterBenchmarkSuite.java deleted file mode 100644 index 53dff71..0000000 --- a/test/com/google/caliper/examples/FormatterBenchmarkSuite.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper.examples; - -import com.google.caliper.Benchmark; -import com.google.caliper.DefaultBenchmarkSuite; -import com.google.caliper.Param; -import com.google.caliper.Runner; - -import java.util.Formatter; - -/** - * Compares Formatter against hand-written StringBuilder code. - */ -public class FormatterBenchmarkSuite extends DefaultBenchmarkSuite { - - class Formatter_NoFormatting extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - Formatter f = new Formatter(); - f.format("this is a reasonably short string that doesn't actually need any formatting"); - } - return null; - } - } - - class StringBuilder_NoFormatting extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - StringBuilder sb = new StringBuilder(); - sb.append("this is a reasonably short string that doesn't actually need any formatting"); - } - return null; - } - } - - class Formatter_OneInt extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - Formatter f = new Formatter(); - f.format("this is a reasonably short string that has an int %d in it", i); - } - return null; - } - } - - class StringBuilder_OneInt extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - StringBuilder sb = new StringBuilder(); - sb.append("this is a reasonably short string that has an int "); - sb.append(i); - sb.append(" in it"); - } - return null; - } - } - - class Formatter_OneString extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - Formatter f = new Formatter(); - f.format("this is a reasonably short string that has a string %s in it", "hello"); - } - return null; - } - } - - class StringBuilder_OneString extends Benchmark { - public Object run(int trials) { - for (int i = 0; i < trials; i++) { - StringBuilder sb = new StringBuilder(); - sb.append("this is a reasonably short string that has a string "); - sb.append("hello"); - sb.append(" in it"); - } - return null; - } - } - - public static void main(String[] args) { - Runner.main(FormatterBenchmarkSuite.class, args); - } -} diff --git a/test/com/google/caliper/examples/IntModBenchmark.java b/test/com/google/caliper/examples/IntModBenchmark.java new file mode 100644 index 0000000..86e85e7 --- /dev/null +++ b/test/com/google/caliper/examples/IntModBenchmark.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +/** + * Measures several candidate implementations for mod(). + */ +public class IntModBenchmark extends SimpleBenchmark { + private static final int M = (1 << 16) - 1; + + public int timeConditional(int reps) { + int dummy = 5; + for (int i = 0; i < reps; i++) { + dummy += Integer.MAX_VALUE + conditionalMod(dummy, M); + } + return dummy; + } + + private static int conditionalMod(int a, int m) { + int r = a % m; + return r < 0 ? r + m : r; + } + + public int timeDoubleRemainder(int reps) { + int dummy = 5; + for (int i = 0; i < reps; i++) { + dummy += Integer.MAX_VALUE + doubleRemainderMod(dummy, M); + } + return dummy; + } + + private static int doubleRemainderMod(int a, int m) { + return (int) (((a % m) + (long) m) % m); + } + + public int timeRightShiftingMod(int reps) { + int dummy = 5; + for (int i = 0; i < reps; i++) { + dummy += Integer.MAX_VALUE + rightShiftingMod(dummy, M); + } + return dummy; + } + + private static int rightShiftingMod(int a, int m) { + long r = a % m; + return (int) (r + ((r >> 63) & m)); + } + + public int timeLeftShiftingMod(int reps) { + int dummy = 5; + for (int i = 0; i < reps; i++) { + dummy += Integer.MAX_VALUE + leftShiftingMod(dummy, M); + } + return dummy; + } + + private static int leftShiftingMod(int a, int m) { + return (int) ((a + (((long) m) << 32)) % m); + } + + public int timeWrongMod(int reps) { + int dummy = 5; + for (int i = 0; i < reps; i++) { + dummy += Integer.MAX_VALUE + dummy % M; + } + return dummy; + } + + // TODO: remove this from all examples when IDE plugins are ready + public static void main(String[] args) throws Exception { + Runner.main(IntModBenchmark.class, args); + } +} \ No newline at end of file diff --git a/test/com/google/caliper/examples/ListIterationBenchmark.java b/test/com/google/caliper/examples/ListIterationBenchmark.java new file mode 100644 index 0000000..53bcdf8 --- /dev/null +++ b/test/com/google/caliper/examples/ListIterationBenchmark.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Measures iterating through list elements. + */ +public class ListIterationBenchmark extends SimpleBenchmark { + @Param private int length; + + private static final Collection lengthValues = Arrays.asList(0, 10, 100, 1000); + + private List list; + private Object[] array; + + @Override protected void setUp() { + array = new Object[length]; + for (int i = 0; i < length; i++) { + array[i] = new Object(); + } + + list = new AbstractList() { + @Override public int size() { + return length; + } + + @Override public Object get(int i) { + return array[i]; + } + }; + } + + public int timeListIteration(int reps) { + int count = 0; + for (int i = 0; i < reps; i++) { + for (Object value : list) { + count ^= value.hashCode(); // prevent overoptimization + } + } + return count; // ignored + } + + public int timeArrayIteration(int reps) { + int count = 0; + for (int i = 0; i < reps; i++) { + for (Object value : array) { + count ^= value.hashCode(); // prevent overoptimization + } + } + return count; // ignored + } + + // TODO: remove this from all examples when IDE plugins are ready + public static void main(String[] args) throws Exception { + Runner.main(ListIterationBenchmark.class, args); + } +} \ No newline at end of file diff --git a/test/com/google/caliper/examples/ListIterationBenchmarkSuite.java b/test/com/google/caliper/examples/ListIterationBenchmarkSuite.java deleted file mode 100644 index 0ed7197..0000000 --- a/test/com/google/caliper/examples/ListIterationBenchmarkSuite.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper.examples; - -import com.google.caliper.Benchmark; -import com.google.caliper.DefaultBenchmarkSuite; -import com.google.caliper.Param; -import com.google.caliper.Runner; - -import java.util.*; - -/** - * Measures iterating through list elements. - */ -public class ListIterationBenchmarkSuite extends DefaultBenchmarkSuite { - - @Param private int length; - - private static Collection lengthValues = Arrays.asList(0, 10, 100, 1000); - - private List list; - private Object[] array; - - @Override protected void setUp() throws Exception { - array = new Object[length]; - for (int i = 0; i < length; i++) { - array[i] = new Object(); - } - - list = new AbstractList() { - @Override public int size() { - return length; - } - - @Override public Object get(int i) { - return array[i]; - } - }; - } - - class ListIterateBenchmark extends Benchmark { - @Override public Object run(int trials) throws Exception { - int count = 0; - for (int i = 0; i < trials; i++) { - for (Object value : list) { - count ^= (value == Boolean.TRUE) ? i : 0; - } - } - return count > 0; - } - } - - class ArrayIterateBenchmark extends Benchmark { - @Override public Object run(int trials) throws Exception { - int count = 0; - for (int i = 0; i < trials; i++) { - for (Object value : array) { - count ^= (value == Boolean.TRUE) ? i : 0; - } - } - return count > 0; - } - } - - public static void main(String[] args) { - Runner.main(ListIterationBenchmarkSuite.class, args); - } -} \ No newline at end of file diff --git a/test/com/google/caliper/examples/PrimitiveDoubleToStringBenchmark.java b/test/com/google/caliper/examples/PrimitiveDoubleToStringBenchmark.java new file mode 100644 index 0000000..592acdc --- /dev/null +++ b/test/com/google/caliper/examples/PrimitiveDoubleToStringBenchmark.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.SimpleBenchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Measures the various ways the JDK converts primitive doubles to Strings. + */ +public class PrimitiveDoubleToStringBenchmark extends SimpleBenchmark { + + @Param private double d; + + private static final Collection dValues = Arrays.asList( + Math.PI, + -0.0d, + Double.NEGATIVE_INFINITY, + Double.NaN + ); + + public int timeStringFormat(int reps) { + double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += String.format("%f", value).length(); + } + return dummy; + } + + public int timeToString(int reps) { + double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += ((Double) value).toString().length(); + } + return dummy; + } + + public int timeStringValueOf(int reps) { + double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy += String.valueOf(value).length(); + } + return dummy; + } + + public int timeQuoteTrick(int reps) { + double value = d; + int dummy = 0; + for (int i = 0; i < reps; i++) { + dummy = ("" + value).length(); + } + return dummy; + } + + // TODO: remove this from all examples when IDE plugins are ready + public static void main(String[] args) throws Exception { + Runner.main(PrimitiveDoubleToStringBenchmark.class, args); + } +} \ No newline at end of file diff --git a/test/com/google/caliper/examples/SortBenchmarkSuite.java b/test/com/google/caliper/examples/SortBenchmarkSuite.java deleted file mode 100644 index e92fc10..0000000 --- a/test/com/google/caliper/examples/SortBenchmarkSuite.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.caliper.examples; - -import com.google.caliper.Benchmark; -import com.google.caliper.DefaultBenchmarkSuite; -import com.google.caliper.Param; -import com.google.caliper.Runner; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Random; -import java.util.Collection; - -/** - * Measures sorting on different distributions of integers. - */ -public class SortBenchmarkSuite extends DefaultBenchmarkSuite { - - @Param int length; - - static Collection lengthValues = Arrays.asList(10, 100, 1000, 10000); - - @Param Distribution distribution; - - static Collection distributionValues = EnumSet.allOf(Distribution.class); - - int[] values; - int[] copy; - - @Override protected void setUp() throws Exception { - values = distribution.create(length); - copy = new int[length]; - } - - class ArraysSortBenchmark extends Benchmark { - public Object run(int trials) throws Exception { - int result = 0; - for (int i = 0; i < trials; i++) { - System.arraycopy(values, 0, copy, 0, values.length); - Arrays.sort(copy); - result ^= copy[0]; - } - return result; - } - } - - enum Distribution { - SAWTOOTH { - @Override - int[] create(int length) { - int[] result = new int[length]; - for (int i = 0; i < length; i += 5) { - result[i] = 0; - result[i + 1] = 1; - result[i + 2] = 2; - result[i + 3] = 3; - result[i + 4] = 4; - } - return result; - } - }, - INCREASING { - @Override - int[] create(int length) { - int[] result = new int[length]; - for (int i = 0; i < length; i++) { - result[i] = i; - } - return result; - } - }, - DECREASING { - @Override - int[] create(int length) { - int[] result = new int[length]; - for (int i = 0; i < length; i++) { - result[i] = length - i; - } - return result; - } - }, - RANDOM { - @Override - int[] create(int length) { - Random random = new Random(); - int[] result = new int[length]; - for (int i = 0; i < length; i++) { - result[i] = random.nextInt(); - } - return result; - } - }; - - abstract int[] create(int length); - } - - public static void main(String[] args) { - Runner.main(SortBenchmarkSuite.class, args); - } -} diff --git a/test/com/google/caliper/examples/StringBuilderBenchmark.java b/test/com/google/caliper/examples/StringBuilderBenchmark.java new file mode 100644 index 0000000..2fa6819 --- /dev/null +++ b/test/com/google/caliper/examples/StringBuilderBenchmark.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.caliper.examples; + +import com.google.caliper.Benchmark; +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Tests the performance of various StringBuilder methods. + */ +public class StringBuilderBenchmark extends SimpleBenchmark { + + @Param int length; + static Collection lengthValues = Arrays.asList(1, 10, 100); + + public void timeAppendBoolean(int reps) { + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(true); + } + } + } + + public void timeAppendChar(int reps) { + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append('c'); + } + } + } + + public void timeAppendCharArray(int reps) { + char[] chars = "chars".toCharArray(); + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(chars); + } + } + } + + public void timeAppendCharSequence(int reps) { + CharSequence cs = "chars"; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(cs); + } + } + } + + public void timeAppendDouble(int reps) { + double d = 1.2; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(d); + } + } + } + + public void timeAppendFloat(int reps) { + float f = 1.2f; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(f); + } + } + } + + public void timeAppendInt(int reps) { + int n = 123; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(n); + } + } + } + + public void timeAppendLong(int reps) { + long l = 123; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(l); + } + } + } + + public void timeAppendObject(int reps) { + Object o = new Object(); + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(o); + } + } + } + + public void timeAppendString(int reps) { + String s = "chars"; + for (int i = 0; i < reps; ++i) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < length; ++j) { + sb.append(s); + } + } + } +} -- cgit v1.2.3