diff --git a/README b/README index c54683c5..827b7b0e 100644 --- a/README +++ b/README @@ -1,8 +1,13 @@ -To build this project with Maven: +To build this project with Maven (assuming you are in the caliper root directory): +1. cd caliper +# Make sure it builds +1a. mvn eclipse:configure-workspace eclipse:eclipse install -Dmaven.test.skip=true +# Optionally, run the tests +1b. mvn eclipse:configure-workspace eclipse:eclipse install -1. cd caliper -mvn eclipse:configure-workspace eclipse:eclipse install +cd .. -2. To build examples -cd examples -mvn eclipse:configure-workspace eclipse:eclipse install +To build examples +2. cd examples +# There are no tests in the examples +2a. mvn eclipse:configure-workspace eclipse:eclipse install diff --git a/caliper/pom.xml b/caliper/pom.xml index f8c06547..77a7d67d 100644 --- a/caliper/pom.xml +++ b/caliper/pom.xml @@ -151,6 +151,14 @@ package + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + -Xmx1024m + + org.apache.maven.plugins maven-compiler-plugin diff --git a/caliper/src/main/java/com/google/caliper/config/CaliperConfig.java b/caliper/src/main/java/com/google/caliper/config/CaliperConfig.java index 4a8bd093..7bde6db3 100644 --- a/caliper/src/main/java/com/google/caliper/config/CaliperConfig.java +++ b/caliper/src/main/java/com/google/caliper/config/CaliperConfig.java @@ -20,6 +20,16 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import java.io.File; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + import com.google.caliper.api.ResultProcessor; import com.google.caliper.config.VmConfig.Builder; import com.google.caliper.util.Util; @@ -35,16 +45,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import java.io.File; -import java.lang.management.ManagementFactory; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; - /** * Represents caliper configuration. By default, {@code ~/.caliper/config.properties} and * {@code global-config.properties}. diff --git a/caliper/src/main/java/com/google/caliper/runner/ExperimentModule.java b/caliper/src/main/java/com/google/caliper/runner/ExperimentModule.java index c3244347..a6d3121d 100644 --- a/caliper/src/main/java/com/google/caliper/runner/ExperimentModule.java +++ b/caliper/src/main/java/com/google/caliper/runner/ExperimentModule.java @@ -18,10 +18,15 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.text.ParseException; + import com.google.caliper.Param; import com.google.caliper.bridge.WorkerSpec; import com.google.caliper.util.Parser; import com.google.caliper.util.Parsers; +import com.google.caliper.util.Util; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import com.google.inject.AbstractModule; @@ -31,10 +36,6 @@ import com.google.inject.spi.TypeEncounter; import com.google.inject.spi.TypeListener; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.text.ParseException; - /** * A module that binds data specific to a single experiment. */ @@ -57,9 +58,8 @@ public static ExperimentModule forExperiment(Experiment experiment) { experiment.userParameters()); } - public static ExperimentModule forWorkerSpec(WorkerSpec spec) - throws ClassNotFoundException { - Class benchmarkClass = Class.forName(spec.benchmarkSpec.className()); + public static ExperimentModule forWorkerSpec(WorkerSpec spec) throws ClassNotFoundException { + final Class benchmarkClass = Util.lookupClass(spec.benchmarkSpec.className()); Method benchmarkMethod = findBenchmarkMethod(benchmarkClass, spec.benchmarkSpec.methodName(), spec.methodParameterClasses); benchmarkMethod.setAccessible(true); diff --git a/caliper/src/main/java/com/google/caliper/util/Util.java b/caliper/src/main/java/com/google/caliper/util/Util.java index a399ec54..c9971844 100644 --- a/caliper/src/main/java/com/google/caliper/util/Util.java +++ b/caliper/src/main/java/com/google/caliper/util/Util.java @@ -24,10 +24,14 @@ import com.google.common.io.Closer; import com.google.common.io.Resources; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Member; import java.lang.reflect.Modifier; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -35,6 +39,23 @@ import java.util.concurrent.TimeUnit; public final class Util { + + // lookupClass related fields. + private static final File ROOT = new File("."); + private static final URLClassLoader CLASS_LOADER; + + private static URL[] urls; + static { + try { + urls = new URL[] { ROOT.toURI().toURL() }; + } catch (MalformedURLException e) { + System.err.println("Could get root URI, class lookup via Util.lookupClass() will not work. root="+ROOT); + System.err.println(e); + urls = null; + } + CLASS_LOADER = URLClassLoader.newInstance(urls); + } + private Util() {} // Users have no idea that nested classes are identified with '$', not '.', so if class lookup @@ -125,4 +146,9 @@ private static String generateUniqueName(int index) { return generateUniqueName(index / 26 - 1) + generateUniqueName(index % 26); } } + + public static Class lookupClass(String className) throws ClassNotFoundException { + final Class clazz = Class.forName(className, true, CLASS_LOADER); + return clazz; + } } diff --git a/caliper/src/main/java/com/google/caliper/worker/AllocationRecorder.java b/caliper/src/main/java/com/google/caliper/worker/AllocationRecorder.java index 3996e095..d257e9d2 100644 --- a/caliper/src/main/java/com/google/caliper/worker/AllocationRecorder.java +++ b/caliper/src/main/java/com/google/caliper/worker/AllocationRecorder.java @@ -24,7 +24,17 @@ * thread. */ abstract class AllocationRecorder { + + private static final boolean LESS_THAN_JAVA_7 = System.getProperty("java.version").startsWith("1.5") || System.getProperty("java.version").startsWith("1.6"); + + // (Java 1.7+) private boolean firstTime = true; + { + // (Java 1.5, Java 1.6) Allocations seem somewhat non-deterministic, so disable + if (LESS_THAN_JAVA_7) + firstTime = false; + } + /** * Clears the prior state and starts a new recording. diff --git a/caliper/src/main/java/com/google/caliper/worker/WorkerMain.java b/caliper/src/main/java/com/google/caliper/worker/WorkerMain.java index 78e96c9d..dcb965eb 100644 --- a/caliper/src/main/java/com/google/caliper/worker/WorkerMain.java +++ b/caliper/src/main/java/com/google/caliper/worker/WorkerMain.java @@ -18,6 +18,9 @@ import static com.google.inject.Stage.PRODUCTION; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; + import com.google.caliper.bridge.BridgeModule; import com.google.caliper.bridge.CommandLineSerializer; import com.google.caliper.bridge.OpenedSocket; @@ -25,13 +28,11 @@ import com.google.caliper.bridge.WorkerSpec; import com.google.caliper.runner.BenchmarkClassModule; import com.google.caliper.runner.ExperimentModule; +import com.google.caliper.util.Util; import com.google.common.net.InetAddresses; import com.google.inject.Guice; import com.google.inject.Injector; -import java.net.InetSocketAddress; -import java.nio.channels.SocketChannel; - /** * This class is invoked as a subprocess by the Caliper runner parent process; it re-stages * the benchmark and hands it off to the instrument's worker. @@ -49,8 +50,9 @@ public static void main(String[] args) throws Exception { channel.configureBlocking(false); channel.connect(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), request.port)); + final Class clazz = Util.lookupClass(request.benchmarkSpec.className()); Injector workerInjector = Guice.createInjector(PRODUCTION, - new BenchmarkClassModule(Class.forName(request.benchmarkSpec.className())), + new BenchmarkClassModule(clazz), new BridgeModule(), ExperimentModule.forWorkerSpec(request), new WorkerModule(request)); diff --git a/caliper/src/test/java/com/google/caliper/runner/AllocationInstrumentTest.java b/caliper/src/test/java/com/google/caliper/runner/AllocationInstrumentTest.java index ccf0dd49..aaac5b0e 100644 --- a/caliper/src/test/java/com/google/caliper/runner/AllocationInstrumentTest.java +++ b/caliper/src/test/java/com/google/caliper/runner/AllocationInstrumentTest.java @@ -41,6 +41,19 @@ @RunWith(JUnit4.class) public class AllocationInstrumentTest { + private static final boolean LESS_THAN_JAVA_7 = System.getProperty("java.version").startsWith("1.5") || System.getProperty("java.version").startsWith("1.6"); + + // (Java 1.7+) 14 objects and 1960 bytes are the known values for growing an ArrayList from 1 element to 100 elements + private double objects = 14.0; + private double bytes = 1960.0; + { + if (LESS_THAN_JAVA_7) { + // (Java 1.5, 1.6) + objects = 12.0; + bytes = 1824.0; + } + } + @Rule public CaliperTestWatcher runner = new CaliperTestWatcher(); @Test public void getExtraCommandLineArgs() throws Exception { @@ -65,15 +78,12 @@ public void intrinsics() throws Exception { .instrument("allocation") .run(); Trial trial = Iterables.getOnlyElement(runner.trials()); - ImmutableListMultimap measurementsByDescription = - Measurement.indexByDescription(trial.measurements()); - // 14 objects and 1960 bytes are the known values for growing an ArrayList from 1 element to 100 - // elements + ImmutableListMultimap measurementsByDescription = Measurement.indexByDescription(trial.measurements()); for (Measurement objectMeasurement : measurementsByDescription.get("objects")) { - assertEquals(14.0, objectMeasurement.value().magnitude() / objectMeasurement.weight(), 0.001); + assertEquals(objects, objectMeasurement.value().magnitude() / objectMeasurement.weight(), 0.001); } for (Measurement byteMeasurement : measurementsByDescription.get("bytes")) { - assertEquals(1960.0, byteMeasurement.value().magnitude() / byteMeasurement.weight(), 0.001); + assertEquals(bytes, byteMeasurement.value().magnitude() / byteMeasurement.weight(), 0.001); } } diff --git a/caliper/src/test/java/com/google/caliper/runner/ServerSocketServiceTest.java b/caliper/src/test/java/com/google/caliper/runner/ServerSocketServiceTest.java index 8add40b2..d8a7421a 100644 --- a/caliper/src/test/java/com/google/caliper/runner/ServerSocketServiceTest.java +++ b/caliper/src/test/java/com/google/caliper/runner/ServerSocketServiceTest.java @@ -99,7 +99,7 @@ public class ServerSocketServiceTest { } private OpenedSocket openClientConnection() throws IOException { - return OpenedSocket.fromSocket(new Socket(InetAddress.getLoopbackAddress(), port)); + return OpenedSocket.fromSocket(new Socket(InetAddress.getLocalHost(), port)); } /** diff --git a/examples/src/main/java/examples/DemoBenchmark.java b/examples/src/main/java/examples/DemoBenchmark.java index 3313eeeb..3fcfa4de 100644 --- a/examples/src/main/java/examples/DemoBenchmark.java +++ b/examples/src/main/java/examples/DemoBenchmark.java @@ -49,17 +49,17 @@ enum Foo { } } - @Benchmark int something(int reps) { + @Benchmark int something(long reps) { int dummy = 0; - for (int i = 0; i < reps; i++) { + for (long i = 0; i < reps; i++) { dummy += i; } return dummy; } - @Benchmark int somethingElse(int reps) { + @Benchmark int somethingElse(long reps) { int dummy = 0; - for (int i = 0; i < reps; i++) { + for (long i = 0; i < reps; i++) { dummy -= i; } return dummy;