/*
 * 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}
 *
 * @author Kevin Bourrillion
 */
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
   *    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;
    }
  }
}
