1 /*
   2  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package org.openjdk.jmh.runner.options;
  26 
  27 import joptsimple.OptionException;
  28 import joptsimple.OptionParser;
  29 import joptsimple.OptionSet;
  30 import joptsimple.OptionSpec;
  31 import org.openjdk.jmh.annotations.Mode;
  32 import org.openjdk.jmh.annotations.Threads;
  33 import org.openjdk.jmh.profile.Profiler;
  34 import org.openjdk.jmh.profile.ProfilerFactory;
  35 import org.openjdk.jmh.results.format.ResultFormatType;
  36 import org.openjdk.jmh.util.HashMultimap;
  37 import org.openjdk.jmh.util.Multimap;
  38 import org.openjdk.jmh.util.Optional;
  39 
  40 import java.io.IOException;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.Collection;
  44 import java.util.HashSet;
  45 import java.util.List;
  46 import java.util.Set;
  47 import java.util.concurrent.TimeUnit;
  48 
  49 /**
  50  * Class that handles all the command line options.
  51  */
  52 public class CommandLineOptions implements Options {
  53     private static final long serialVersionUID = 5565183446360224399L;
  54 
  55     private final Optional<Integer> iterations;
  56     private final Optional<TimeValue> timeout;
  57     private final Optional<TimeValue> runTime;
  58     private final Optional<Integer> batchSize;
  59     private final Optional<Integer> warmupIterations;
  60     private final Optional<TimeValue> warmupTime;
  61     private final Optional<Integer> warmupBatchSize;
  62     private final List<Mode> benchMode = new ArrayList<Mode>();
  63     private final Optional<Integer> threads;
  64     private final List<Integer> threadGroups = new ArrayList<Integer>();
  65     private final Optional<Boolean> synchIterations;
  66     private final Optional<Boolean> gcEachIteration;
  67     private final Optional<VerboseMode> verbose;
  68     private final Optional<Boolean> failOnError;
  69     private final Set<Class<? extends Profiler>> profilers = new HashSet<Class<? extends Profiler>>();
  70     private final Optional<TimeUnit> timeUnit;
  71     private final Optional<Integer> opsPerInvocation;
  72     private final List<String> regexps = new ArrayList<String>();
  73     private final Optional<Integer> fork;
  74     private final Optional<Integer> warmupFork;
  75     private final Optional<String> output;
  76     private final Optional<String> result;
  77     private final Optional<ResultFormatType> resultFormat;
  78     private final Optional<String> jvm;
  79     private final Optional<Collection<String>> jvmArgs;
  80     private final Optional<Collection<String>> jvmArgsAppend;
  81     private final Optional<Collection<String>> jvmArgsPrepend;
  82     private final List<String> excludes = new ArrayList<String>();
  83     private final Optional<WarmupMode> warmupMode;
  84     private final List<String> warmupMicros = new ArrayList<String>();
  85     private final Multimap<String, String> params = new HashMultimap<String, String>();
  86     private final boolean list;
  87     private final boolean listResultFormats;
  88     private final boolean help;
  89     private final boolean listProfilers;
  90 
  91     private final transient OptionParser parser;
  92 
  93     /**
  94      * Parses the given command line.
  95      * @param argv argument list
  96      * @throws CommandLineOptionException if some options are misspelled
  97      */
  98     public CommandLineOptions(String... argv) throws CommandLineOptionException {
  99         parser = new OptionParser();
 100         parser.formatHelpWith(new OptionFormatter());
 101 
 102         OptionSpec<Integer> optMeasureCount = parser.accepts("i", "Number of measurement iterations to do.")
 103                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 104 
 105         OptionSpec<Integer> optMeasureBatchSize = parser.accepts("bs", "Batch size: number of benchmark method calls per operation. " +
 106                 "(some benchmark modes can ignore this setting)")
 107                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 108 
 109         OptionSpec<String> optMeasureTime = parser.accepts("r", "Time to spend at each measurement iteration.")
 110                 .withRequiredArg().ofType(String.class).describedAs("time");
 111 
 112         OptionSpec<Integer> optWarmupCount = parser.accepts("wi", "Number of warmup iterations to do.")
 113                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 114 
 115         OptionSpec<Integer> optWarmupBatchSize = parser.accepts("wbs", "Warmup batch size: number of benchmark method calls per operation. " +
 116                 "(some benchmark modes can ignore this setting)")
 117                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 118 
 119         OptionSpec<String> optWarmupTime = parser.accepts("w", "Time to spend at each warmup iteration.")
 120                 .withRequiredArg().ofType(String.class).describedAs("time");
 121 
 122         OptionSpec<String> optTimeoutTime = parser.accepts("to", "Timeout for benchmark iteration.")
 123                 .withRequiredArg().ofType(String.class).describedAs("time");
 124 
 125         OptionSpec<String> optThreads = parser.accepts("t", "Number of worker threads to run with.")
 126                 .withRequiredArg().ofType(String.class).describedAs("int");
 127 
 128         OptionSpec<String> optBenchmarkMode = parser.accepts("bm", "Benchmark mode. Available modes are: " + Mode.getKnown())
 129                 .withRequiredArg().ofType(String.class).withValuesSeparatedBy(',').describedAs("mode");
 130 
 131         OptionSpec<Boolean> optSyncIters = parser.accepts("si", "Synchronize iterations?")
 132                 .withOptionalArg().ofType(Boolean.class).describedAs("bool");
 133 
 134         OptionSpec<Boolean> optGC = parser.accepts("gc", "Should JMH force GC between iterations?")
 135                 .withOptionalArg().ofType(Boolean.class).describedAs("bool");
 136 
 137         OptionSpec<Boolean> optFOE = parser.accepts("foe", "Should JMH fail immediately if any benchmark had" +
 138                 " experienced the unrecoverable error?")
 139                 .withOptionalArg().ofType(Boolean.class).describedAs("bool");
 140 
 141         OptionSpec<String> optVerboseMode = parser.accepts("v", "Verbosity mode. Available modes are: " + Arrays.toString(VerboseMode.values()))
 142                 .withRequiredArg().ofType(String.class).describedAs("mode");
 143 
 144         OptionSpec<String> optArgs = parser.nonOptions("Benchmarks to run (regexp+).")
 145                 .describedAs("regexp+");
 146 
 147         OptionSpec<Integer> optForks = parser.accepts("f", "How many times to forks a single benchmark." +
 148                 " Use 0 to disable forking altogether (WARNING: disabling forking may have detrimental" +
 149                 " impact on benchmark and infrastructure reliability, you might want to use different" +
 150                 " warmup mode instead).")
 151                 .withOptionalArg().ofType(Integer.class).describedAs("int");
 152 
 153         OptionSpec<Integer> optWarmupForks = parser.accepts("wf", "How many warmup forks to make " +
 154                 "for a single benchmark. 0 to disable warmup forks.")
 155                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 156 
 157         OptionSpec<String> optOutput = parser.accepts("o", "Redirect human-readable output to file.")
 158                 .withRequiredArg().ofType(String.class).describedAs("filename");
 159 
 160         OptionSpec<String> optOutputResults = parser.accepts("rff", "Write results to given file.")
 161                 .withRequiredArg().ofType(String.class).describedAs("filename");
 162 
 163         OptionSpec<String> optProfilers = parser.accepts("prof", "Use profilers to collect additional data." +
 164                 " See the list of available profilers first.")
 165                 .withRequiredArg().withValuesSeparatedBy(',').ofType(String.class).describedAs("profiler+");
 166 
 167         OptionSpec<Integer> optThreadGroups = parser.accepts("tg", "Override thread group distribution for asymmetric benchmarks.")
 168                 .withRequiredArg().withValuesSeparatedBy(',').ofType(Integer.class).describedAs("int+");
 169 
 170         OptionSpec<String> optJvm = parser.accepts("jvm", "Custom JVM to use when forking (path to JVM executable).")
 171                 .withRequiredArg().ofType(String.class).describedAs("string");
 172 
 173         OptionSpec<String> optJvmArgs = parser.accepts("jvmArgs", "Custom JVM args to use when forking.")
 174                 .withRequiredArg().ofType(String.class).describedAs("string");
 175 
 176         OptionSpec<String> optJvmArgsAppend = parser.accepts("jvmArgsAppend", "Custom JVM args to use when forking (append these)")
 177                 .withRequiredArg().ofType(String.class).describedAs("string");
 178 
 179         OptionSpec<String> optJvmArgsPrepend = parser.accepts("jvmArgsPrepend", "Custom JVM args to use when forking (prepend these)")
 180                 .withRequiredArg().ofType(String.class).describedAs("string");
 181 
 182         OptionSpec<String> optTU = parser.accepts("tu", "Output time unit. Available time units are: [m, s, ms, us, ns].")
 183                 .withRequiredArg().ofType(String.class).describedAs("TU");
 184 
 185         OptionSpec<Integer> optOPI = parser.accepts("opi", "Operations per invocation.")
 186                 .withRequiredArg().ofType(Integer.class).describedAs("int");
 187 
 188         OptionSpec<String> optResultFormat = parser.accepts("rf", "Result format type. See the list of available result formats first.")
 189                 .withRequiredArg().ofType(String.class).describedAs("type");
 190 
 191         OptionSpec<String> optWarmupMode = parser.accepts("wm", "Warmup mode for warming up selected benchmarks. Warmup modes are: " + Arrays.toString(WarmupMode.values()) + ".")
 192                 .withRequiredArg().ofType(String.class).describedAs("mode");
 193 
 194         OptionSpec<String> optExcludes = parser.accepts("e", "Benchmarks to exclude from the run.")
 195                 .withRequiredArg().withValuesSeparatedBy(',').ofType(String.class).describedAs("regexp+");
 196 
 197         OptionSpec<String> optParams = parser.accepts("p", "Benchmark parameters. This option is expected to be used once" +
 198                 " per parameter. Parameter name and parameter values should be separated with equals sign." +
 199                 " Parameter values should be separated with commas.")
 200                 .withRequiredArg().ofType(String.class).describedAs("param={v,}*");
 201 
 202         OptionSpec<String> optWarmupBenchmarks = parser.accepts("wmb", "Warmup benchmarks to include in the run " +
 203                 "in addition to already selected. JMH will not measure these benchmarks, but only use them" +
 204                 " for the warmup.")
 205                 .withRequiredArg().withValuesSeparatedBy(',').ofType(String.class).describedAs("regexp+");
 206 
 207         parser.accepts("l", "List matching benchmarks and exit.");
 208         parser.accepts("lrf", "List result formats.");
 209         parser.accepts("lprof", "List profilers.");
 210         parser.accepts("h", "Display help.");
 211 
 212         try {
 213             OptionSet set = parser.parse(argv);
 214 
 215             if (set.has(optExcludes)) {
 216                 excludes.addAll(optExcludes.values(set));
 217             }
 218 
 219             if (set.has(optWarmupBenchmarks)) {
 220                 warmupMicros.addAll(optWarmupBenchmarks.values(set));
 221             }
 222 
 223             if (set.has(optTU)) {
 224                 String va = optTU.value(set);
 225                 TimeUnit tu;
 226                 if (va.equalsIgnoreCase("ns")) {
 227                     tu = TimeUnit.NANOSECONDS;
 228                 } else if (va.equalsIgnoreCase("us")) {
 229                     tu = TimeUnit.MICROSECONDS;
 230                 } else if (va.equalsIgnoreCase("ms")) {
 231                     tu = TimeUnit.MILLISECONDS;
 232                 } else if (va.equalsIgnoreCase("s")) {
 233                     tu = TimeUnit.SECONDS;
 234                 } else if (va.equalsIgnoreCase("m")) {
 235                     tu = TimeUnit.MINUTES;
 236                 } else if (va.equalsIgnoreCase("h")) {
 237                     tu = TimeUnit.HOURS;
 238                 } else {
 239                     throw new CommandLineOptionException("Unknown time unit: " + va);
 240                 }
 241                 timeUnit = Optional.of(tu);
 242             } else {
 243                 timeUnit = Optional.none();
 244             }
 245 
 246             opsPerInvocation = Optional.eitherOf(optOPI.value(set));
 247 
 248             if (set.has(optWarmupMode)) {
 249                 try {
 250                     warmupMode = Optional.of(WarmupMode.valueOf(optWarmupMode.value(set)));
 251                 } catch (IllegalArgumentException iae) {
 252                     throw new CommandLineOptionException(iae.getMessage(), iae);
 253                 }
 254             } else {
 255                 warmupMode = Optional.none();
 256             }
 257 
 258             if (set.has(optResultFormat)) {
 259                 try {
 260                     resultFormat = Optional.of(ResultFormatType.valueOf(optResultFormat.value(set).toUpperCase()));
 261                 } catch (IllegalArgumentException iae) {
 262                     throw new CommandLineOptionException(iae.getMessage(), iae);
 263                 }
 264             } else {
 265                 resultFormat = Optional.none();
 266             }
 267 
 268             help = set.has("h");
 269             list = set.has("l");
 270             listResultFormats = set.has("lrf");
 271             listProfilers = set.has("lprof");
 272 
 273             iterations = Optional.eitherOf(optMeasureCount.value(set));
 274 
 275             batchSize = Optional.eitherOf(optMeasureBatchSize.value(set));
 276 
 277             if (set.has(optMeasureTime)) {
 278                 String value = optMeasureTime.value(set);
 279                 try {
 280                     runTime = Optional.of(TimeValue.fromString(value));
 281                 } catch (IllegalArgumentException iae) {
 282                     throw new CommandLineOptionException(iae.getMessage(), iae);
 283                 }
 284             } else {
 285                 runTime = Optional.none();
 286             }
 287 
 288             warmupIterations = Optional.eitherOf(optWarmupCount.value(set));
 289 
 290             warmupBatchSize = Optional.eitherOf(optWarmupBatchSize.value(set));
 291 
 292             if (set.has(optWarmupTime)) {
 293                 String value = optWarmupTime.value(set);
 294                 try {
 295                     warmupTime = Optional.of(TimeValue.fromString(value));
 296                 } catch (IllegalArgumentException iae) {
 297                     throw new CommandLineOptionException(iae.getMessage(), iae);
 298                 }
 299             } else {
 300                 warmupTime = Optional.none();
 301             }
 302 
 303             if (set.has(optTimeoutTime)) {
 304                 String value = optTimeoutTime.value(set);
 305                 try {
 306                     timeout = Optional.of(TimeValue.fromString(value));
 307                 } catch (IllegalArgumentException iae) {
 308                     throw new CommandLineOptionException(iae.getMessage(), iae);
 309                 }
 310             } else {
 311                 timeout = Optional.none();
 312             }
 313 
 314             if (set.has(optThreads)) {
 315                 String v = optThreads.value(set);
 316                 if (v.equalsIgnoreCase("max")) {
 317                     threads = Optional.of(Threads.MAX);
 318                 } else {
 319                     try {
 320                         threads = Optional.of(Integer.valueOf(v));
 321                     } catch (IllegalArgumentException iae) {
 322                         throw new CommandLineOptionException(iae.getMessage(), iae);
 323                     }
 324                 }
 325             } else {
 326                 threads = Optional.none();
 327             }
 328 
 329             if (set.has(optBenchmarkMode)) {
 330                 try {
 331                     List<Mode> modes = new ArrayList<Mode>();
 332                     for (String m : optBenchmarkMode.values(set)) {
 333                         modes.add(Mode.deepValueOf(m));
 334                     }
 335                     benchMode.addAll(modes);
 336                 } catch (IllegalArgumentException iae) {
 337                     throw new CommandLineOptionException(iae.getMessage(), iae);
 338                 }
 339             }
 340 
 341             if (set.has(optSyncIters)) {
 342                 if (set.hasArgument(optSyncIters)) {
 343                     synchIterations = Optional.of(optSyncIters.value(set));
 344                 } else {
 345                     synchIterations = Optional.of(true);
 346                 }
 347             } else {
 348                 synchIterations = Optional.none();
 349             }
 350 
 351             if (set.has(optGC)) {
 352                 if (set.hasArgument(optGC)) {
 353                     gcEachIteration = Optional.of(optGC.value(set));
 354                 } else {
 355                     gcEachIteration = Optional.of(true);
 356                 }
 357             } else {
 358                 gcEachIteration = Optional.none();
 359             }
 360 
 361             if (set.has(optFOE)) {
 362                 if (set.hasArgument(optFOE)) {
 363                     failOnError = Optional.of(optFOE.value(set));
 364                 } else {
 365                     failOnError = Optional.of(true);
 366                 }
 367             } else {
 368                 failOnError = Optional.none();
 369             }
 370 
 371             if (set.has(optVerboseMode)) {
 372                 try {
 373                     if (set.hasArgument(optVerboseMode)) {
 374                         verbose = Optional.of(VerboseMode.valueOf(set.valueOf(optVerboseMode).toUpperCase()));
 375                     } else {
 376                         verbose = Optional.of(VerboseMode.EXTRA);
 377                     }
 378                 } catch (IllegalArgumentException iae) {
 379                     throw new CommandLineOptionException(iae.getMessage(), iae);
 380                 }
 381             } else {
 382                 verbose = Optional.none();
 383             }
 384 
 385             regexps.addAll(set.valuesOf(optArgs));
 386 
 387             if (set.has(optForks)) {
 388                 if (set.hasArgument(optForks)) {
 389                     fork = Optional.of(optForks.value(set));
 390                 } else {
 391                     fork = Optional.of(1);
 392                 }
 393             } else {
 394                 fork = Optional.none();
 395             }
 396 
 397             warmupFork = Optional.eitherOf(optWarmupForks.value(set));
 398             output = Optional.eitherOf(optOutput.value(set));
 399             result = Optional.eitherOf(optOutputResults.value(set));
 400 
 401             if (set.has(optProfilers)) {
 402                 try {
 403                     for (String m : optProfilers.values(set)) {
 404                         Class<? extends Profiler> pClass = ProfilerFactory.getProfilerByName(m);
 405                         if (pClass == null) {
 406                             throw new CommandLineOptionException("Unable to find profiler: " + m);
 407                         }
 408                         profilers.add(pClass);
 409                     }
 410                 } catch (IllegalArgumentException iae) {
 411                     throw new CommandLineOptionException(iae.getMessage(), iae);
 412                 }
 413             }
 414 
 415             if (set.has(optThreadGroups)) {
 416                 threadGroups.addAll(set.valuesOf(optThreadGroups));
 417             }
 418 
 419             jvm = Optional.eitherOf(optJvm.value(set));
 420 
 421             if (set.hasArgument(optJvmArgs)) {
 422                 jvmArgs = Optional.<Collection<String>>of(Arrays.asList(optJvmArgs.value(set).trim().split("[ ]+")));
 423             } else {
 424                 jvmArgs = Optional.none();
 425             }
 426 
 427             if (set.hasArgument(optJvmArgsAppend)) {
 428                 jvmArgsAppend = Optional.<Collection<String>>of(Arrays.asList(optJvmArgsAppend.value(set).trim().split("[ ]+")));
 429             } else {
 430                 jvmArgsAppend = Optional.none();
 431             }
 432 
 433             if (set.hasArgument(optJvmArgsPrepend)) {
 434                 jvmArgsPrepend = Optional.<Collection<String>>of(Arrays.asList(optJvmArgsPrepend.value(set).trim().split("[ ]+")));
 435             } else {
 436                 jvmArgsPrepend = Optional.none();
 437             }
 438 
 439             if (set.hasArgument(optParams)) {
 440                 for (String p : optParams.values(set)) {
 441                     String[] keys = p.split("=");
 442                     if (keys.length != 2) {
 443                         throw new CommandLineOptionException("Unable to parse parameter string \"" + p + "\"");
 444                     }
 445                     params.putAll(keys[0], Arrays.asList(keys[1].split(",")));
 446                 }
 447             }
 448 
 449         } catch (OptionException e) {
 450             throw new CommandLineOptionException(e.getMessage(), e);
 451         }
 452     }
 453 
 454     public void showHelp() throws IOException {
 455         parser.printHelpOn(System.err);
 456     }
 457 
 458     public void listProfilers() {
 459         StringBuilder supported = new StringBuilder();
 460         StringBuilder unsupported = new StringBuilder();
 461 
 462         List<Class<? extends Profiler>> discoveredProfilers = ProfilerFactory.getDiscoveredProfilers();
 463 
 464         for (Class<? extends Profiler> s : ProfilerFactory.getAvailableProfilers()) {
 465             List<String> initMessages = new ArrayList<String>();
 466             if (ProfilerFactory.checkSupport(s, initMessages)) {
 467                 supported.append(String.format("%20s: %s %s\n",
 468                         ProfilerFactory.getLabel(s),
 469                         ProfilerFactory.getDescription(s),
 470                         discoveredProfilers.contains(s) ? "(discovered)" : ""));
 471             } else {
 472                 unsupported.append(String.format("%20s: %s %s\n",
 473                         ProfilerFactory.getLabel(s),
 474                         ProfilerFactory.getDescription(s),
 475                         discoveredProfilers.contains(s) ? "(discovered)" : ""));
 476                 for (String im : initMessages) {
 477                     unsupported.append(String.format("%20s  %s\n", "", im));
 478                 }
 479                 unsupported.append("\n");
 480             }
 481         }
 482 
 483         if (!supported.toString().isEmpty()) {
 484             System.out.println("Supported profilers:\n" + supported.toString());
 485         }
 486 
 487         if (!unsupported.toString().isEmpty()) {
 488             System.out.println("Unsupported profilers:\n" + unsupported.toString());
 489         }
 490     }
 491 
 492     public void listResultFormats() {
 493         StringBuilder sb = new StringBuilder();
 494 
 495         for (ResultFormatType f : ResultFormatType.values()) {
 496             sb.append(f.toString().toLowerCase());
 497             sb.append(", ");
 498         }
 499         sb.setLength(sb.length() - 2);
 500 
 501         System.out.println("Available formats: " + sb.toString());
 502     }
 503 
 504     public boolean shouldList() {
 505         return list;
 506     }
 507 
 508     public boolean shouldListResultFormats() {
 509         return listResultFormats;
 510     }
 511 
 512     public boolean shouldHelp() {
 513         return help;
 514     }
 515 
 516     public boolean shouldListProfilers() {
 517         return listProfilers;
 518     }
 519 
 520     @Override
 521     public Optional<WarmupMode> getWarmupMode() {
 522         return warmupMode;
 523     }
 524 
 525     @Override
 526     public List<String> getIncludes() {
 527         return regexps;
 528     }
 529 
 530     @Override
 531     public List<String> getExcludes() {
 532         return excludes;
 533     }
 534 
 535     @Override
 536     public List<String> getWarmupIncludes() {
 537         return warmupMicros;
 538     }
 539 
 540     @Override
 541     public Optional<String> getJvm() {
 542         return jvm;
 543     }
 544 
 545     @Override
 546     public Optional<Collection<String>> getJvmArgs() {
 547         return jvmArgs;
 548     }
 549 
 550     @Override
 551     public Optional<Collection<String>> getJvmArgsAppend() {
 552         return jvmArgsAppend;
 553     }
 554 
 555     @Override
 556     public Optional<Collection<String>> getJvmArgsPrepend() {
 557         return jvmArgsPrepend;
 558     }
 559 
 560     @Override
 561     public Optional<Collection<String>> getParameter(String name) {
 562         Collection<String> list = params.get(name);
 563         if (list == null || list.isEmpty()){
 564             return Optional.none();
 565         } else {
 566             return Optional.of(list);
 567         }
 568     }
 569 
 570     @Override
 571     public Optional<Integer> getForkCount() {
 572         return fork;
 573     }
 574 
 575     @Override
 576     public Optional<Integer> getWarmupForkCount() {
 577         return warmupFork;
 578     }
 579 
 580     @Override
 581     public Optional<String> getOutput() {
 582         return output;
 583     }
 584 
 585     @Override
 586     public Optional<ResultFormatType> getResultFormat() {
 587         return resultFormat;
 588     }
 589 
 590     @Override
 591     public Optional<String> getResult() {
 592         return result;
 593     }
 594 
 595     @Override
 596     public Optional<Integer> getMeasurementIterations() {
 597         return iterations;
 598     }
 599 
 600     @Override
 601     public Optional<Integer> getMeasurementBatchSize() {
 602         return batchSize;
 603     }
 604 
 605     @Override
 606     public Optional<TimeValue> getMeasurementTime() {
 607         return runTime;
 608     }
 609 
 610     @Override
 611     public Optional<TimeValue> getWarmupTime() {
 612         return warmupTime;
 613     }
 614 
 615     @Override
 616     public Optional<Integer> getWarmupIterations() {
 617         return warmupIterations;
 618     }
 619 
 620     @Override
 621     public Optional<Integer> getWarmupBatchSize() {
 622         return warmupBatchSize;
 623     }
 624 
 625     @Override
 626     public Optional<Integer> getThreads() {
 627         return threads;
 628     }
 629 
 630     @Override
 631     public Optional<int[]> getThreadGroups() {
 632         if (threadGroups.isEmpty()) {
 633             return Optional.none();
 634         } else {
 635             int[] r = new int[threadGroups.size()];
 636             for (int c = 0; c < r.length; c++) {
 637                 r[c] = threadGroups.get(c);
 638             }
 639             return Optional.of(r);
 640         }
 641     }
 642 
 643     @Override
 644     public Optional<Boolean> shouldDoGC() {
 645         return gcEachIteration;
 646     }
 647 
 648     @Override
 649     public Optional<Boolean> shouldSyncIterations() {
 650         return synchIterations;
 651     }
 652 
 653     @Override
 654     public Optional<VerboseMode> verbosity() {
 655         return verbose;
 656     }
 657 
 658     @Override
 659     public Optional<TimeUnit> getTimeUnit() {
 660         return timeUnit;
 661     }
 662 
 663     @Override
 664     public Optional<Integer> getOperationsPerInvocation() {
 665         return opsPerInvocation;
 666     }
 667 
 668     @Override
 669     public Optional<Boolean> shouldFailOnError() {
 670         return failOnError;
 671     }
 672 
 673     @Override
 674     public Set<Class<? extends Profiler>> getProfilers() {
 675         return profilers;
 676     }
 677 
 678     @Override
 679     public Collection<Mode> getBenchModes() {
 680         return new HashSet<Mode>(benchMode);
 681     }
 682 
 683     @Override
 684     public Optional<TimeValue> getTimeout() {
 685         return timeout;
 686     }
 687 }