Added version 0.5-rc1
Change-Id: Ic21eda3c659eadf3a4229ae5618e9ce1e96b4aa7
diff --git a/tutorial/Tutorial.java b/tutorial/Tutorial.java
new file mode 100644
index 0000000..625d387
--- /dev/null
+++ b/tutorial/Tutorial.java
@@ -0,0 +1,187 @@
+/*
+ * 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 tutorial;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+
+/**
+ * Caliper tutorial. To run the example benchmarks in this file:
+ * {@code CLASSPATH=... [caliper_home]/caliper tutorial.Tutorial.Benchmark1}
+ */
+public class Tutorial {
+
+ /*
+ * We begin the Caliper tutorial with the simplest benchmark you can write.
+ * We'd like to know how efficient the method System.nanoTime() is.
+ *
+ * Notice:
+ *
+ * - We write a class that extends com.google.caliper.SimpleBenchmark.
+ * - It contains a public instance method whose name begins with 'time' and
+ * which accepts a single 'int reps' parameter.
+ * - The body of the method simply executes the code we wish to measure,
+ * 'reps' times.
+ *
+ * Example run:
+ *
+ * $ CLASSPATH=build/classes/test caliper tutorial.Tutorial.Benchmark1
+ * [real-time results appear on this line]
+ *
+ * Summary report for tutorial.Tutorial$Benchmark1:
+ *
+ * Benchmark ns
+ * --------- ---
+ * NanoTime 233
+ */
+ public static class Benchmark1 extends SimpleBenchmark {
+ public void timeNanoTime(int reps) {
+ for (int i = 0; i < reps; i++) {
+ System.nanoTime();
+ }
+ }
+ }
+
+ /*
+ * Now let's compare two things: nanoTime() versus currentTimeMillis().
+ * Notice:
+ *
+ * - We simply add another method, following the same rules as the first.
+ *
+ * Example run output:
+ *
+ * Benchmark ns
+ * ----------------- ---
+ * NanoTime 248
+ * CurrentTimeMillis 118
+ */
+ public static class Benchmark2 extends SimpleBenchmark {
+ public void timeNanoTime(int reps) {
+ for (int i = 0; i < reps; i++) {
+ System.nanoTime();
+ }
+ }
+ public void timeCurrentTimeMillis(int reps) {
+ for (int i = 0; i < reps; i++) {
+ System.currentTimeMillis();
+ }
+ }
+ }
+
+ /*
+ * Let's try iterating over a large array. This seems simple enough, but
+ * there is a problem!
+ */
+ public static class Benchmark3 extends SimpleBenchmark {
+ private final int[] array = new int[1000000];
+
+ @SuppressWarnings("UnusedDeclaration") // IDEA tries to warn us!
+ public void timeArrayIteration_BAD(int reps) {
+ for (int i = 0; i < reps; i++) {
+ for (int ignoreMe : array) {}
+ }
+ }
+ }
+
+ /*
+ * Caliper reported that the benchmark above ran in 4 nanoseconds.
+ *
+ * Wait, what?
+ *
+ * How can it possibly iterate over a million zeroes in 4 ns!?
+ *
+ * It is very important to sanity-check benchmark results with common sense!
+ * In this case, we're indeed getting a bogus result. The problem is that the
+ * Java Virtual Machine is too smart: it detected the fact that the loop was
+ * producing no actual result, so it simply compiled it right out. The method
+ * never looped at all. To fix this, we need to use a dummy result value.
+ *
+ * Notice:
+ *
+ * - We simply change the 'time' method from 'void' to any return type we
+ * wish. Then we return a value that can't be known without actually
+ * performing the work, and thus we defeat the runtime optimizations.
+ * - We're no longer timing *just* the code we want to be testing - our
+ * result will now be inflated by the (small) cost of addition. This is an
+ * unfortunate fact of life with microbenchmarking. In fact, we were
+ * already inflated by the cost of an int comparison, "i < reps" as it was.
+ *
+ * With this change, Caliper should report a much more realistic value, more
+ * on the order of an entire millisecond.
+ */
+ public static class Benchmark4 extends SimpleBenchmark {
+ private final int[] array = new int[1000000];
+
+ public int timeArrayIteration_fixed(int reps) {
+ int dummy = 0;
+ for (int i = 0; i < reps; i++) {
+ for (int doNotIgnoreMe : array) {
+ dummy += doNotIgnoreMe;
+ }
+ }
+ return dummy; // framework ignores this, but it has served its purpose!
+ }
+ }
+
+ /*
+ * Now we'd like to know how various other *sizes* of arrays perform. We
+ * don't want to have to cut and paste the whole benchmark just to provide a
+ * different size. What we need is a parameter!
+ *
+ * When you run this benchmark the same way you ran the previous ones, you'll
+ * now get an error: "No values provided for benchmark parameter 'size'".
+ * You can provide the value requested at the command line like this:
+ *
+ * [caliper_home]/caliper tutorial.Tutorial.Benchmark5 -Dsize=100}
+ *
+ * You'll see output like this:
+ *
+ * Benchmark size ns
+ * -------------- ---- ---
+ * ArrayIteration 100 51
+ *
+ * Now that we've parameterized our benchmark, things are starting to get fun.
+ * Try passing '-Dsize=10,100,1000' and see what happens!
+ *
+ * Benchmark size ns
+ * -------------- ---- -----------------------------------
+ * ArrayIteration 10 7 |
+ * ArrayIteration 100 49 ||||
+ * ArrayIteration 1000 477 ||||||||||||||||||||||||||||||
+ *
+ */
+ public static class Benchmark5 extends SimpleBenchmark {
+ @Param int size; // set automatically by framework
+
+ private int[] array; // set by us, in setUp()
+
+ @Override protected void setUp() {
+ // @Param values are guaranteed to have been injected by now
+ array = new int[size];
+ }
+
+ public int timeArrayIteration(int reps) {
+ int dummy = 0;
+ for (int i = 0; i < reps; i++) {
+ for (int doNotIgnoreMe : array) {
+ dummy += doNotIgnoreMe;
+ }
+ }
+ return dummy;
+ }
+ }
+}