Package com.google.caliper.options

Source Code of com.google.caliper.options.ParsedOptions

/*
* Copyright (C) 2011 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.options;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.MINUTES;

import com.google.caliper.options.CommandLineParser.Leftovers;
import com.google.caliper.options.CommandLineParser.Option;
import com.google.caliper.util.InvalidCommandException;
import com.google.caliper.util.ShortDuration;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;

import java.io.File;
import java.util.List;
import java.util.Map;

final class ParsedOptions implements CaliperOptions {
  public static ParsedOptions from(String[] args) throws InvalidCommandException {
    ParsedOptions options = new ParsedOptions();

    CommandLineParser<ParsedOptions> parser = CommandLineParser.forClass(ParsedOptions.class);
    try {
      parser.parseAndInject(args, options);
    } catch (InvalidCommandException e) {
      e.setUsage(USAGE);
      throw e;
    }
    return options;
  }

  private ParsedOptions() {
  }

  // --------------------------------------------------------------------------
  // Dry run -- simple boolean, needs to be checked in some methods
  // --------------------------------------------------------------------------

  @Option({"-n", "--dry-run"})
  private boolean dryRun;

  @Override public boolean dryRun() {
    return dryRun;
  }

  private void dryRunIncompatible(String optionName) throws InvalidCommandException {
    // This only works because CLP does field injection before method injection
    if (dryRun) {
      throw new InvalidCommandException("Option not available in dry-run mode: " + optionName);
    }
  }

  // --------------------------------------------------------------------------
  // Delimiter -- injected early so methods can use it
  // --------------------------------------------------------------------------

  @Option({"-d", "--delimiter"})
  private String delimiter = ",";

  private ImmutableSet<String> split(String string) {
    return ImmutableSet.copyOf(Splitter.on(delimiter).split(string));
  }

  // --------------------------------------------------------------------------
  // Benchmark method names to run
  // --------------------------------------------------------------------------

  private ImmutableSet<String> benchmarkNames = ImmutableSet.of();

  @Option({"-b", "--benchmark"})
  private void setBenchmarkNames(String benchmarksString) {
    benchmarkNames = split(benchmarksString);
  }

  @Override public ImmutableSet<String> benchmarkMethodNames() {
    return benchmarkNames;
  }

  // --------------------------------------------------------------------------
  // Verbose?
  // --------------------------------------------------------------------------

  @Option({"-v", "--verbose"})
  private boolean verbose = false;

  @Override public boolean verbose() {
    return verbose;
  }

  // --------------------------------------------------------------------------
  // Print configuration?
  // --------------------------------------------------------------------------

  @Option({"-p", "--print-config"})
  private boolean printConfiguration = false;

  @Override public boolean printConfiguration() {
    return printConfiguration;
  }

  // --------------------------------------------------------------------------
  // Trials
  // --------------------------------------------------------------------------

  private int trials = 1;

  @Option({"-t", "--trials"})
  private void setTrials(int trials) throws InvalidCommandException {
    dryRunIncompatible("trials");
    if (trials < 1) {
      throw new InvalidCommandException("trials must be at least 1: " + trials);
    }
    this.trials = trials;
  }

  @Override public int trialsPerScenario() {
    return trials;
  }

  // --------------------------------------------------------------------------
  // Time limit
  // --------------------------------------------------------------------------

  private ShortDuration runTime = ShortDuration.of(5, MINUTES);

  @Option({"-l", "--time-limit"})
  private void setTimeLimit(String timeLimitString) throws InvalidCommandException {
    try {
      this.runTime = ShortDuration.valueOf(timeLimitString);
    } catch (IllegalArgumentException e) {
      throw new InvalidCommandException("Invalid time limit: " + timeLimitString);
    }
  }

  @Override public ShortDuration timeLimit() {
    return runTime;
  }

  // --------------------------------------------------------------------------
  // Run name
  // --------------------------------------------------------------------------

  private String runName = "";

  @Option({"-r", "--run-name"})
  private void setRunName(String runName) {
    this.runName = checkNotNull(runName);
  }

  @Override public String runName() {
    return runName;
  }

  // --------------------------------------------------------------------------
  // VM specifications
  // --------------------------------------------------------------------------

  private ImmutableSet<String> vmNames = ImmutableSet.of();

  @Option({"-m", "--vm"})
  private void setVms(String vmsString) throws InvalidCommandException {
    dryRunIncompatible("vm");
    vmNames = split(vmsString);
  }

  @Override public ImmutableSet<String> vmNames() {
    return vmNames;
  }

  // --------------------------------------------------------------------------
  // Measuring instruments to use
  // --------------------------------------------------------------------------

  private static final ImmutableSet<String> DEFAULT_INSTRUMENT_NAMES =
      new ImmutableSet.Builder<String>()
      .add("allocation")
      .add("runtime")
      .build();

  private ImmutableSet<String> instrumentNames = DEFAULT_INSTRUMENT_NAMES;

  @Option({"-i", "--instrument"})
  private void setInstruments(String instrumentsString) {
    instrumentNames = split(instrumentsString);
  }

  @Override public ImmutableSet<String> instrumentNames() {
    return instrumentNames;
  }

// --------------------------------------------------------------------------
  // Benchmark parameters
  // --------------------------------------------------------------------------

  private Multimap<String, String> mutableUserParameters = ArrayListMultimap.create();

  @Option("-D")
  private void addParameterSpec(String nameAndValues) throws InvalidCommandException {
    addToMultimap(nameAndValues, mutableUserParameters);
  }

  @Override public ImmutableSetMultimap<String, String> userParameters() {
    // de-dup values, but keep in order
    return new ImmutableSetMultimap.Builder<String, String>()
        .orderKeysBy(Ordering.natural())
        .putAll(mutableUserParameters)
        .build();
  }

  // --------------------------------------------------------------------------
  // VM arguments
  // --------------------------------------------------------------------------

  private Multimap<String, String> mutableVmArguments = ArrayListMultimap.create();

  @Option("-J")
  private void addVmArgumentsSpec(String nameAndValues) throws InvalidCommandException {
    dryRunIncompatible("-J");
    addToMultimap(nameAndValues, mutableVmArguments);
  }

  @Override public ImmutableSetMultimap<String, String> vmArguments() {
    // de-dup values, but keep in order
    return new ImmutableSetMultimap.Builder<String, String>()
        .orderKeysBy(Ordering.natural())
        .putAll(mutableVmArguments)
        .build();
  }

  // --------------------------------------------------------------------------
  // VM arguments
  // --------------------------------------------------------------------------

  private final Map<String, String> mutableConfigPropertes = Maps.newHashMap();

  @Option("-C")
  private void addConfigProperty(String nameAndValue) throws InvalidCommandException {
    List<String> tokens = splitProperty(nameAndValue);
    mutableConfigPropertes.put(tokens.get(0), tokens.get(1));
  }

  @Override public ImmutableMap<String, String> configProperties() {
    return ImmutableMap.copyOf(mutableConfigPropertes);
  }

  // --------------------------------------------------------------------------
  // Location of .caliper
  // --------------------------------------------------------------------------

  private File caliperDirectory = new File(System.getProperty("user.home"), ".caliper");

  @Option({"--directory"})
  private void setCaliperDirectory(String path) {
    caliperDirectory = new File(path);
  }

  @Override public File caliperDirectory() {
    return caliperDirectory;
  }

  // --------------------------------------------------------------------------
  // Location of config.properties
  // --------------------------------------------------------------------------

  private Optional<File> caliperConfigFile = Optional.absent();

  @Option({"-c", "--config"})
  private void setCaliperConfigFile(String filename) {
    caliperConfigFile = Optional.of(new File(filename));
  }

  @Override public File caliperConfigFile() {
    return caliperConfigFile.or(new File(caliperDirectory, "config.properties"));
  }


  // --------------------------------------------------------------------------
  // Leftover - benchmark class name
  // --------------------------------------------------------------------------

  private String benchmarkClassName;

  @Leftovers
  private void setLeftovers(ImmutableList<String> leftovers) throws InvalidCommandException {
    if (leftovers.isEmpty()) {
      throw new InvalidCommandException("No benchmark class specified");
    }
    if (leftovers.size() > 1) {
      throw new InvalidCommandException("Extra stuff, expected only class name: " + leftovers);
    }
    this.benchmarkClassName = leftovers.get(0);
  }

  @Override public String benchmarkClassName() {
    return benchmarkClassName;
  }

  // --------------------------------------------------------------------------
  // Helper methods
  // --------------------------------------------------------------------------

  private static List<String> splitProperty(String propertyString) throws InvalidCommandException {
    List<String> tokens = ImmutableList.copyOf(Splitter.on('=').limit(2).split(propertyString));
    if (tokens.size() != 2) {
      throw new InvalidCommandException("no '=' found in: " + propertyString);
    }
    return tokens;
  }

  private void addToMultimap(String nameAndValues, Multimap<String, String> multimap)
      throws InvalidCommandException {
    List<String> tokens = splitProperty(nameAndValues);
    String name = tokens.get(0);
    String values = tokens.get(1);

    if (multimap.containsKey(name)) {
      throw new InvalidCommandException("multiple parameter sets for: " + name);
    }
    multimap.putAll(name, split(values));
  }

  @Override public String toString() {
    return Objects.toStringHelper(this)
        .add("benchmarkClassName", this.benchmarkClassName())
        .add("benchmarkMethodNames", this.benchmarkMethodNames())
        .add("benchmarkParameters", this.userParameters())
        .add("dryRun", this.dryRun())
        .add("instrumentNames", this.instrumentNames())
        .add("vms", this.vmNames())
        .add("vmArguments", this.vmArguments())
        .add("trials", this.trialsPerScenario())
        .add("verbose", this.verbose())
        .add("printConfig", this.printConfiguration())
        .add("delimiter", this.delimiter)
        .add("caliperConfigFile", this.caliperConfigFile)
        .toString();
  }

  // --------------------------------------------------------------------------
  // Usage
  // --------------------------------------------------------------------------

  // TODO(kevinb): kinda nice if CommandLineParser could autogenerate most of this...
  // TODO(kevinb): a test could actually check that we don't exceed 79 columns.
  private static final ImmutableList<String> USAGE = ImmutableList.of(
      "Usage:",
      " java com.google.caliper.runner.CaliperMain <benchmark_class_name> [options...]",
      "",
      "Options:",
      " -h, --help         print this message",
      " -n, --dry-run      instead of measuring, execute a single rep for each scenario",
      "                    in-process",
      " -b, --benchmark    comma-separated list of benchmark methods to run; 'foo' is",
      "                    an alias for 'timeFoo' (default: all found in class)",
      " -m, --vm           comma-separated list of VMs to test on; possible values are",
      "                    configured in Caliper's configuration file (default:",
      "                    whichever VM caliper itself is running in, only)",
      " -i, --instrument   comma-separated list of measuring instruments to use; possible ",
      "                    values are configured in Caliper's configuration file ",
      "                    (default: \"" + Joiner.on(",").join(DEFAULT_INSTRUMENT_NAMES) + "\")",
      " -t, --trials       number of independent trials to peform per benchmark scenario; ",
      "                    a positive integer (default: 1)",
      " -l, --time-limit   maximum length of time allowed for a single trial; use 0 to allow ",
      "                    trials to run indefinitely. (default: 30s) ",
      " -r, --run-name     a user-friendly string used to identify the run",
      " -v, --verbose      in addition to normal console output, display a raw feed of very",
      "                    detailed information from the worker (GC, compilation events, etc.).",
      "                    Runner output from loggers can be controlled via",
      "                    $HOME/.caliper/logging.properties",
      " -p, --print-config print the effective configuration that will be used by Caliper",
      " -d, --delimiter    separator used in options that take multiple values (default: ',')",
      " -c, --config       location of Caliper's configuration file (default:",
      "                    $HOME/.caliper/config.properties)",
      " --directory        location of Caliper's configuration and data directory ",
      "                    (default: $HOME/.caliper)",
      "",
      " -Dparam=val1,val2,...",
      "     Specifies the values to inject into the 'param' field of the benchmark",
      "     class; if multiple values or parameters are specified in this way, caliper",
      "     will try all possible combinations.",
      "",
      // commented out until this flag is fixed
      // " -JdisplayName='vm arg list choice 1,vm arg list choice 2,...'",
      // "     Specifies alternate sets of VM arguments to pass. As with any variable,",
      // "     caliper will test all possible combinations. Example:",
      // "     -Jmemory='-Xms32m -Xmx32m,-Xms512m -Xmx512m'",
      // "",
      " -CconfigProperty=value",
      "     Specifies a value for any property that could otherwise be specified in ",
      "     $HOME/.caliper/config.properties. Properties specified on the command line",
      "     will override those specified in the file.",
      "",
      "See http://code.google.com/p/caliper/wiki/CommandLineOptions for more details.",
      "");
}
TOP

Related Classes of com.google.caliper.options.ParsedOptions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.