diff options
Diffstat (limited to 'caliper/src/main/java/com/google/caliper/Arguments.java')
-rw-r--r-- | caliper/src/main/java/com/google/caliper/Arguments.java | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/caliper/src/main/java/com/google/caliper/Arguments.java b/caliper/src/main/java/com/google/caliper/Arguments.java new file mode 100644 index 0000000..cceb079 --- /dev/null +++ b/caliper/src/main/java/com/google/caliper/Arguments.java @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2010 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; + +import com.google.caliper.UserException.DisplayUsageException; +import com.google.caliper.UserException.IncompatibleArgumentsException; +import com.google.caliper.UserException.InvalidParameterValueException; +import com.google.caliper.UserException.MultipleBenchmarkClassesException; +import com.google.caliper.UserException.NoBenchmarkClassException; +import com.google.caliper.UserException.UnrecognizedOptionException; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; + +import java.io.File; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * Parse command line arguments for the runner and in-process runner. + */ +public final class Arguments { + private String suiteClassName; + + /** JVMs to run in the benchmark */ + private final Set<String> userVms = Sets.newLinkedHashSet(); + + /** + * Parameter values specified by the user on the command line. Parameters with + * no value in this multimap will get their values from the benchmark suite. + */ + private final Multimap<String, String> userParameters = LinkedHashMultimap.create(); + + /** + * VM parameters like {memory=[-Xmx64,-Xmx128],jit=[-client,-server]} + */ + private final Multimap<String, String> vmParameters = LinkedHashMultimap.create(); + + private int trials = 1; + private long warmupMillis = 3000; + private long runMillis = 1000; + private String timeUnit = null; + private String instanceUnit = null; + private String memoryUnit = null; + private File saveResultsFile = null; + private File uploadResultsFile = null; + private boolean captureVmLog = false; + private boolean printScore = false; + private boolean measureMemory = false; + private boolean debug = false; + private int debugReps = defaultDebugReps; + private MeasurementType measurementType; + private MeasurementType primaryMeasurementType; + + /** + * A signal that indicates a JSON object interleaved with the process output. + * Should be short, but unlikely to show up in the processes natural output. + */ + private String marker = "//ZxJ/"; + + private static final String defaultDelimiter = ","; + private static final int defaultDebugReps = 1000; + + public String getSuiteClassName() { + return suiteClassName; + } + + public Set<String> getUserVms() { + return userVms; + } + + public int getTrials() { + return trials; + } + + public Multimap<String, String> getVmParameters() { + return vmParameters; + } + + public Multimap<String, String> getUserParameters() { + return userParameters; + } + + public long getWarmupMillis() { + return warmupMillis; + } + + public long getRunMillis() { + return runMillis; + } + + public String getTimeUnit() { + return timeUnit; + } + + public String getInstanceUnit() { + return instanceUnit; + } + + public String getMemoryUnit() { + return memoryUnit; + } + + public File getSaveResultsFile() { + return saveResultsFile; + } + + public File getUploadResultsFile() { + return uploadResultsFile; + } + + public boolean getCaptureVmLog() { + return captureVmLog; + } + + public boolean printScore() { + return printScore; + } + + public boolean getMeasureMemory() { + return measureMemory; + } + + public MeasurementType getMeasurementType() { + return measurementType; + } + + public MeasurementType getPrimaryMeasurementType() { + return primaryMeasurementType; + } + + public boolean getDebug() { + return debug; + } + + public int getDebugReps() { + return debugReps; + } + + public String getMarker() { + return marker; + } + + public static Arguments parse(String[] argsArray) { + Arguments result = new Arguments(); + + Iterator<String> args = Iterators.forArray(argsArray); + String delimiter = defaultDelimiter; + Map<String, String> userParameterStrings = Maps.newLinkedHashMap(); + Map<String, String> vmParameterStrings = Maps.newLinkedHashMap(); + String vmString = null; + boolean standardRun = false; + while (args.hasNext()) { + String arg = args.next(); + + if ("--help".equals(arg)) { + throw new DisplayUsageException(); + } + + if (arg.startsWith("-D") || arg.startsWith("-J")) { + + /* + * Handle user parameters (-D) and VM parameters (-J) of these forms: + * + * -Dlength=100 + * -Jmemory=-Xmx1024M + * -Dlength=100,200 + * -Jmemory=-Xmx1024M,-Xmx2048M + * -Dlength 100 + * -Jmemory -Xmx1024M + * -Dlength 100,200 + * -Jmemory -Xmx1024M,-Xmx2048M + */ + + String name; + String value; + int equalsSign = arg.indexOf('='); + if (equalsSign == -1) { + name = arg.substring(2); + value = args.next(); + } else { + name = arg.substring(2, equalsSign); + value = arg.substring(equalsSign + 1); + } + + String previousValue; + if (arg.startsWith("-D")) { + previousValue = userParameterStrings.put(name, value); + } else { + previousValue = vmParameterStrings.put(name, value); + } + if (previousValue != null) { + throw new UserException.DuplicateParameterException(arg); + } + standardRun = true; + // TODO: move warmup/run to caliperrc + } else if ("--captureVmLog".equals(arg)) { + result.captureVmLog = true; + standardRun = true; + } else if ("--warmupMillis".equals(arg)) { + result.warmupMillis = Long.parseLong(args.next()); + standardRun = true; + } else if ("--runMillis".equals(arg)) { + result.runMillis = Long.parseLong(args.next()); + standardRun = true; + } else if ("--trials".equals(arg)) { + String value = args.next(); + try { + result.trials = Integer.parseInt(value); + if (result.trials < 1) { + throw new UserException.InvalidTrialsException(value); + } + } catch (NumberFormatException e) { + throw new UserException.InvalidTrialsException(value); + } + standardRun = true; + } else if ("--vm".equals(arg)) { + if (vmString != null) { + throw new UserException.DuplicateParameterException(arg); + } + vmString = args.next(); + standardRun = true; + } else if ("--delimiter".equals(arg)) { + delimiter = args.next(); + standardRun = true; + } else if ("--timeUnit".equals(arg)) { + result.timeUnit = args.next(); + standardRun = true; + } else if ("--instanceUnit".equals(arg)) { + result.instanceUnit = args.next(); + standardRun = true; + } else if ("--memoryUnit".equals(arg)) { + result.memoryUnit = args.next(); + standardRun = true; + } else if ("--saveResults".equals(arg) || "--xmlSave".equals(arg)) { + // TODO: unsupport legacy --xmlSave + result.saveResultsFile = new File(args.next()); + standardRun = true; + } else if ("--uploadResults".equals(arg)) { + result.uploadResultsFile = new File(args.next()); + } else if ("--printScore".equals(arg)) { + result.printScore = true; + standardRun = true; + } else if ("--measureMemory".equals(arg)) { + result.measureMemory = true; + standardRun = true; + } else if ("--debug".equals(arg)) { + result.debug = true; + } else if ("--debug-reps".equals(arg)) { + String value = args.next(); + try { + result.debugReps = Integer.parseInt(value); + if (result.debugReps < 1) { + throw new UserException.InvalidDebugRepsException(value); + } + } catch (NumberFormatException e) { + throw new UserException.InvalidDebugRepsException(value); + } + } else if ("--marker".equals(arg)) { + result.marker = args.next(); + } else if ("--measurementType".equals(arg)) { + String measurementType = args.next(); + try { + result.measurementType = MeasurementType.valueOf(measurementType); + } catch (Exception e) { + throw new InvalidParameterValueException(arg, measurementType); + } + standardRun = true; + } else if ("--primaryMeasurementType".equals(arg)) { + String measurementType = args.next().toUpperCase(); + try { + result.primaryMeasurementType = MeasurementType.valueOf(measurementType); + } catch (Exception e) { + throw new InvalidParameterValueException(arg, measurementType); + } + standardRun = true; + } else if (arg.startsWith("-")) { + throw new UnrecognizedOptionException(arg); + + } else { + if (result.suiteClassName != null) { + throw new MultipleBenchmarkClassesException(result.suiteClassName, arg); + } + result.suiteClassName = arg; + } + } + + Splitter delimiterSplitter = Splitter.on(delimiter); + + if (vmString != null) { + Iterables.addAll(result.userVms, delimiterSplitter.split(vmString)); + } + + Set<String> duplicates = Sets.intersection( + userParameterStrings.keySet(), vmParameterStrings.keySet()); + if (!duplicates.isEmpty()) { + throw new UserException.DuplicateParameterException(duplicates); + } + + for (Map.Entry<String, String> entry : userParameterStrings.entrySet()) { + result.userParameters.putAll(entry.getKey(), delimiterSplitter.split(entry.getValue())); + } + for (Map.Entry<String, String> entry : vmParameterStrings.entrySet()) { + result.vmParameters.putAll(entry.getKey(), delimiterSplitter.split(entry.getValue())); + } + + if (standardRun && result.uploadResultsFile != null) { + throw new IncompatibleArgumentsException("--uploadResults"); + } + + if (result.suiteClassName == null && result.uploadResultsFile == null) { + throw new NoBenchmarkClassException(); + } + + if (result.primaryMeasurementType != null + && result.primaryMeasurementType != MeasurementType.TIME && !result.measureMemory) { + throw new IncompatibleArgumentsException( + "--primaryMeasurementType " + result.primaryMeasurementType.toString().toLowerCase()); + } + + return result; + } + + public static void printUsage() { + System.out.println(); + System.out.println("Usage: Runner [OPTIONS...] <benchmark>"); + System.out.println(); + System.out.println(" <benchmark>: a benchmark class or suite"); + System.out.println(); + System.out.println("OPTIONS"); + System.out.println(); + System.out.println(" -D<param>=<value>: fix a benchmark parameter to a given value."); + System.out.println(" Multiple values can be supplied by separating them with the"); + System.out.println(" delimiter specified in the --delimiter argument."); + System.out.println(); + System.out.println(" For example: \"-Dfoo=bar,baz,bat\""); + System.out.println(); + System.out.println(" \"benchmark\" is a special parameter that can be used to specify"); + System.out.println(" which benchmark methods to run. For example, if a benchmark has"); + System.out.println(" the method \"timeFoo\", it can be run alone by using"); + System.out.println(" \"-Dbenchmark=Foo\". \"benchmark\" also accepts a delimiter"); + System.out.println(" separated list of methods to run."); + System.out.println(); + System.out.println(" -J<param>=<value>: set a JVM argument to the given value."); + System.out.println(" Multiple values can be supplied by separating them with the"); + System.out.println(" delimiter specified in the --delimiter argument."); + System.out.println(); + System.out.println(" For example: \"-JmemoryMax=-Xmx32M,-Xmx512M\""); + System.out.println(); + System.out.println(" --delimiter <delimiter>: character or string to use as a delimiter"); + System.out.println(" for parameter and vm values."); + System.out.println(" Default: \"" + defaultDelimiter + "\""); + System.out.println(); + System.out.println(" --warmupMillis <millis>: duration to warmup each benchmark"); + System.out.println(); + System.out.println(" --runMillis <millis>: duration to execute each benchmark"); + System.out.println(); + System.out.println(" --captureVmLog: record the VM's just-in-time compiler and GC logs."); + System.out.println(" This may slow down or break benchmark display tools."); + System.out.println(); + System.out.println(" --measureMemory: measure the number of allocations done and the amount of"); + System.out.println(" memory used by invocations of the benchmark."); + System.out.println(" Default: off"); + System.out.println(); + System.out.println(" --vm <vm>: executable to test benchmark on. Multiple VMs may be passed"); + System.out.println(" in as a list separated by the delimiter specified in the"); + System.out.println(" --delimiter argument."); + System.out.println(); + System.out.println(" --timeUnit <unit>: unit of time to use for result. Depends on the units"); + System.out.println(" defined in the benchmark's getTimeUnitNames() method, if defined."); + System.out.println(" Default Options: ns, us, ms, s"); + System.out.println(); + System.out.println(" --instanceUnit <unit>: unit to use for allocation instances result."); + System.out.println(" Depends on the units defined in the benchmark's"); + System.out.println(" getInstanceUnitNames() method, if defined."); + System.out.println(" Default Options: instances, K instances, M instances, B instances"); + System.out.println(); + System.out.println(" --memoryUnit <unit>: unit to use for allocation memory size result."); + System.out.println(" Depends on the units defined in the benchmark's"); + System.out.println(" getMemoryUnitNames() method, if defined."); + System.out.println(" Default Options: B, KB, MB, GB"); + System.out.println(); + System.out.println(" --saveResults <file/dir>: write results to this file or directory"); + System.out.println(); + System.out.println(" --printScore: if present, also display an aggregate score for this run,"); + System.out.println(" where higher is better. This number has no particular meaning,"); + System.out.println(" but can be compared to scores from other runs that use the exact"); + System.out.println(" same arguments."); + System.out.println(); + System.out.println(" --uploadResults <file/dir>: upload this file or directory of files"); + System.out.println(" to the web app. This argument ends Caliper early and is thus"); + System.out.println(" incompatible with all other arguments."); + System.out.println(); + System.out.println(" --debug: run without measurement for use with debugger or profiling."); + System.out.println(); + System.out.println(" --debug-reps: fixed number of reps to run with --debug."); + System.out.println(" Default: \"" + defaultDebugReps + "\""); + + // adding new options? don't forget to update executeForked() + } +} |