All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.caliper.runner.ExperimentingRunnerModule Maven / Gradle / Ivy

There is a newer version: 1.0-beta-3
Show newest version
/*
 * Copyright (C) 2012 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.runner;

import com.google.caliper.api.ResultProcessor;
import com.google.caliper.config.CaliperConfig;
import com.google.caliper.config.InstrumentConfig;
import com.google.caliper.model.Host;
import com.google.caliper.model.Run;
import com.google.caliper.options.CaliperOptions;
import com.google.caliper.runner.Instrument.Instrumentation;
import com.google.caliper.util.InvalidCommandException;
import com.google.caliper.util.ShortDuration;
import com.google.caliper.util.Util;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Service;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;

import org.joda.time.Instant;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.Executors;

/**
 * Configures a {@link CaliperRun} that performs experiments.
 */
final class ExperimentingRunnerModule extends AbstractModule {
  private static final String RUNNER_MAX_PARALLELISM_OPTION = "runner.maxParallelism";

  @Override protected void configure() {
    install(new TrialModule());
    install(new RunnerModule());
    bind(CaliperRun.class).to(ExperimentingCaliperRun.class);
    bind(ExperimentSelector.class).to(FullCartesianExperimentSelector.class);
    Multibinder services = Multibinder.newSetBinder(binder(), Service.class);
    services.addBinding().to(ServerSocketService.class);
    services.addBinding().to(TrialOutputFactoryService.class);
    bind(TrialOutputFactory.class).to(TrialOutputFactoryService.class);
  }

  @Provides
  ListeningExecutorService provideExecutorService(CaliperConfig config) {
    int poolSize = Integer.parseInt(config.properties().get(RUNNER_MAX_PARALLELISM_OPTION));
    return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(poolSize));
  }

  @LocalPort 
  @Provides
  int providePortNumber(ServerSocketService serverSocketService) {
    return serverSocketService.getPort();
  }

  @Provides ImmutableSet provideResultProcessors(CaliperConfig config,
      Injector injector) {
    ImmutableSet.Builder builder = ImmutableSet.builder();
    for (Class processorClass : config.getConfiguredResultProcessors()) {
      builder.add(injector.getInstance(processorClass));
    }
    return builder.build();
  }

  @Provides UUID provideUuid() {
    return UUID.randomUUID();
  }

  @Provides @BenchmarkParameters ImmutableSetMultimap provideBenchmarkParameters(
      BenchmarkClass benchmarkClass, CaliperOptions options) throws InvalidBenchmarkException {
    return benchmarkClass.userParameters().fillInDefaultsFor(options.userParameters());
  }

  @Provides @Singleton Host provideHost(EnvironmentGetter environmentGetter) {
    return environmentGetter.getHost();
  }

  @Provides @Singleton Run provideRun(UUID id, CaliperOptions options, Instant startTime) {
    return new Run.Builder(id).label(options.runName()).startTime(startTime).build();
  }

  @Provides ImmutableSet provideInstruments(Injector injector,
      CaliperOptions options, final CaliperConfig config) throws InvalidCommandException {
    ImmutableSet.Builder builder = ImmutableSet.builder();
    ImmutableSet configuredInstruments = config.getConfiguredInstruments();
    for (final String instrumentName : options.instrumentNames()) {
      if (!configuredInstruments.contains(instrumentName)) {
        throw new InvalidCommandException("%s is not a configured instrument (%s). "
            + "use --print-config to see the configured instruments.",
                instrumentName, configuredInstruments);
      }
      final InstrumentConfig instrumentConfig = config.getInstrumentConfig(instrumentName);
      Injector instrumentInjector = injector.createChildInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(InstrumentConfig.class).toInstance(instrumentConfig);
        }

        @Provides @InstrumentOptions ImmutableMap provideInstrumentOptions(
            InstrumentConfig config) {
          return config.options();
        }

        @Provides @InstrumentName String provideInstrumentName() {
          return instrumentName;
        }
      });
      String className = instrumentConfig.className();
      try {
        Class clazz =
            Util.lenientClassForName(className).asSubclass(Instrument.class);
        builder.add(instrumentInjector.getInstance(clazz));
      } catch (ClassNotFoundException e) {
        throw new InvalidCommandException("Cannot find instrument class '%s'", className);
      } catch (ProvisionException e) {
        throw new InvalidInstrumentException("Could not create the instrument %s", className);
      }
    }
    return builder.build();
  }

  @Provides @Singleton @NanoTimeGranularity ShortDuration provideNanoTimeGranularity(
      NanoTimeGranularityTester tester) {
    return tester.testNanoTimeGranularity();
  }

  @Provides ImmutableSet provideInstrumentations(CaliperOptions options,
      BenchmarkClass benchmarkClass, ImmutableSet instruments)
          throws InvalidBenchmarkException {
    ImmutableSet.Builder builder = ImmutableSet.builder();
    ImmutableSet benchmarkMethodNames = options.benchmarkMethodNames();
    Set unusedBenchmarkNames = new HashSet(benchmarkMethodNames);
    for (Instrument instrument : instruments) {
      for (Method method : findAllBenchmarkMethods(benchmarkClass.benchmarkClass(), instrument)) {
        if (benchmarkMethodNames.isEmpty() || benchmarkMethodNames.contains(method.getName())) {
          builder.add(instrument.createInstrumentation(method));
          unusedBenchmarkNames.remove(method.getName());
        }
      }
    }
    if (!unusedBenchmarkNames.isEmpty()) {
      throw new InvalidBenchmarkException(
          "Invalid benchmark method(s) specified in options: " + unusedBenchmarkNames);
    }
    return builder.build();
  }

  private static ImmutableSortedSet findAllBenchmarkMethods(Class benchmarkClass,
      Instrument instrument) throws InvalidBenchmarkException {
    ImmutableSortedSet.Builder result = ImmutableSortedSet.orderedBy(
        Ordering.natural().onResultOf(new Function() {
          @Override public String apply(Method method) {
            return method.getName();
          }
        }));
    Set benchmarkMethodNames = new HashSet();
    Set overloadedMethodNames = new TreeSet();
    for (Method method : benchmarkClass.getDeclaredMethods()) {
      if (instrument.isBenchmarkMethod(method)) {
        method.setAccessible(true);
        result.add(method);
        if (!benchmarkMethodNames.add(method.getName())) {
          overloadedMethodNames.add(method.getName());
        }
      }
    }
    if (!overloadedMethodNames.isEmpty()) {
      throw new InvalidBenchmarkException(
          "Overloads are disallowed for benchmark methods, found overloads of %s in benchmark %s",
          overloadedMethodNames,
          benchmarkClass);
    }
    return result.build();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy