changeset 342:f35ebe6117bf

Use Optional in Option interface, move the defaults out of option parsing code.
author shade
date Mon, 13 Jan 2014 20:10:37 +0400
parents 310927fb382e
children f479fb156309
files jmh-core/src/main/java/org/openjdk/jmh/output/results/ResultFormatType.java jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/BenchmarkParams.java jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/Defaults.java jmh-core/src/main/java/org/openjdk/jmh/util/internal/Optional.java jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestOptions.java
diffstat 12 files changed, 267 insertions(+), 285 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/output/results/ResultFormatType.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/output/results/ResultFormatType.java	Mon Jan 13 20:10:37 2014 +0400
@@ -30,10 +30,5 @@
     CSV,
     SCSV,
     JSON,
-    ;
-
-    public static ResultFormatType defaultType() {
-        return NONE;
-    }
 
 }
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseMicroBenchmarkHandler.java	Mon Jan 13 20:10:37 2014 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jmh.profile.ProfilerType;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.parameters.BenchmarkParams;
+import org.openjdk.jmh.runner.parameters.Defaults;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -75,14 +76,14 @@
             }
         };
         this.format = format;
-        this.timeUnit = options.getTimeUnit();
+        this.timeUnit = options.getTimeUnit().orElse(null);
     }
 
     private static List<Profiler> createProfilers(Options options) {
         List<Profiler> list = new ArrayList<Profiler>();
         // register the profilers
         for (ProfilerType prof : options.getProfilers()) {
-            list.add(prof.createInstance(options.verbosity()));
+            list.add(prof.createInstance(options.verbosity().orElse(Defaults.DEFAULT_VERBOSITY)));
         }
         return list;
     }
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseRunner.java	Mon Jan 13 20:10:37 2014 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jmh.output.format.OutputFormat;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.parameters.BenchmarkParams;
+import org.openjdk.jmh.runner.parameters.Defaults;
 import org.openjdk.jmh.runner.parameters.IterationParams;
 import org.openjdk.jmh.util.ClassUtils;
 import org.openjdk.jmh.util.internal.Multimap;
@@ -104,7 +105,7 @@
             return runBenchmark(executionParams, handler);
         } catch (Throwable ex) {
             out.exception(ex);
-            if (this.options.shouldFailOnError()) {
+            if (options.shouldFailOnError().orElse(Defaults.SHOULD_FAIL_ON_ERROR)) {
                 throw new IllegalStateException(ex.getMessage(), ex);
             }
         } finally {
@@ -177,7 +178,7 @@
      * @return true if we did
      */
     public boolean runSystemGC() {
-        if (options.shouldDoGC()) {
+        if (options.shouldDoGC().orElse(Defaults.SHOULD_DO_GC)) {
             List<GarbageCollectorMXBean> enabledBeans = new ArrayList<GarbageCollectorMXBean>();
 
             long beforeGcCount = 0;
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/LoopMicroBenchmarkHandler.java	Mon Jan 13 20:10:37 2014 +0400
@@ -33,6 +33,7 @@
 import org.openjdk.jmh.output.format.OutputFormat;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.parameters.BenchmarkParams;
+import org.openjdk.jmh.runner.parameters.Defaults;
 import org.openjdk.jmh.runner.parameters.IterationParams;
 import org.openjdk.jmh.runner.parameters.TimeValue;
 
@@ -67,7 +68,7 @@
         super(format, microbenchmark, clazz, options, executionParams);
         this.method = method;
         this.shouldSynchIterations = (microbenchmark.getMode() != Mode.SingleShotTime) && executionParams.shouldSynchIterations();
-        this.shouldFailOnError = options.shouldFailOnError();
+        this.shouldFailOnError = options.shouldFailOnError().orElse(Defaults.SHOULD_FAIL_ON_ERROR);
     }
 
     /**
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Mon Jan 13 20:10:37 2014 +0400
@@ -29,13 +29,14 @@
 import org.openjdk.jmh.link.BinaryLinkServer;
 import org.openjdk.jmh.logic.results.BenchResult;
 import org.openjdk.jmh.logic.results.RunResult;
+import org.openjdk.jmh.output.format.OutputFormat;
 import org.openjdk.jmh.output.format.OutputFormatFactory;
-import org.openjdk.jmh.output.format.OutputFormat;
 import org.openjdk.jmh.output.results.ResultFormat;
 import org.openjdk.jmh.output.results.ResultFormatFactory;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.VerboseMode;
 import org.openjdk.jmh.runner.parameters.BenchmarkParams;
+import org.openjdk.jmh.runner.parameters.Defaults;
 import org.openjdk.jmh.util.InputStreamDrainer;
 import org.openjdk.jmh.util.internal.HashMultimap;
 import org.openjdk.jmh.util.internal.Multimap;
@@ -99,19 +100,19 @@
     private static OutputFormat createOutputFormat(Options options) {
         PrintStream out;
         // setup OutputFormat singleton
-        if (options.getOutput() == null) {
-            out = System.out;
-        } else {
+        if (options.getOutput().hasValue()) {
             try {
-                out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(options.getOutput()))));
+                out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(options.getOutput().get()))));
                 System.setOut(out); // override to print everything to file
             } catch (FileNotFoundException ex) {
                 Logger.getLogger(Runner.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
                 throw new IllegalStateException(ex);
             }
+        } else {
+            out = System.out;
         }
 
-        return OutputFormatFactory.createFormatInstance(out, options.verbosity());
+        return OutputFormatFactory.createFormatInstance(out, options.verbosity().orElse(Defaults.DEFAULT_VERBOSITY));
     }
 
     public void list() {
@@ -152,7 +153,7 @@
         if (benchmarks.isEmpty()) {
             out.println("No matching benchmarks. Miss-spelled regexp?");
 
-            if (options.verbosity() != VerboseMode.EXTRA) {
+            if (options.verbosity().orElse(Defaults.DEFAULT_VERBOSITY) != VerboseMode.EXTRA) {
                 out.println("Use " + VerboseMode.EXTRA + " verbose mode to debug the pattern matching.");
             } else {
                 list();
@@ -165,7 +166,7 @@
 
         // override the benchmark types;
         // this may yield new benchmark records
-        if (options.getBenchModes() != null) {
+        if (!options.getBenchModes().isEmpty()) {
             List<BenchmarkRecord> newBenchmarks = new ArrayList<BenchmarkRecord>();
             for (BenchmarkRecord br : benchmarks) {
                 for (Mode m : options.getBenchModes()) {
@@ -199,7 +200,7 @@
         out.flush();
         out.close();
 
-        ResultFormat resultFormat = ResultFormatFactory.getInstance(options.getResultFormat(), options.getResult());
+        ResultFormat resultFormat = ResultFormatFactory.getInstance(options.getResultFormat().orElse(Defaults.RESULT_FORMAT), options.getResult().orElse(Defaults.RESULT_FILE));
         resultFormat.writeOut(results);
 
         return results;
@@ -214,7 +215,7 @@
         if (warmupMicrosRegexp != null && !warmupMicrosRegexp.isEmpty()) {
             warmupBenches.addAll(list.find(out, warmupMicrosRegexp, Collections.<String>emptyList()));
         }
-        if (options.getWarmupMode().isBulk()) {
+        if (options.getWarmupMode().orElse(Defaults.DEFAULT_WARMUP_MODE).isBulk()) {
             warmupBenches.addAll(benchmarks);
         }
 
@@ -225,7 +226,7 @@
         for (BenchmarkRecord br : benchmarks) {
             BenchmarkParams params = new BenchmarkParams(options, br, ActionMode.UNDEF);
             if (params.getForks() <= 0) {
-                if (options.getWarmupMode().isIndi()) {
+                if (options.getWarmupMode().orElse(Defaults.DEFAULT_WARMUP_MODE).isIndi()) {
                     r.addWarmupMeasurement(br);
                 } else {
                     r.addMeasurement(br);
@@ -245,7 +246,7 @@
         if (warmupMicrosRegexp != null && !warmupMicrosRegexp.isEmpty()) {
             warmupBenches.addAll(list.find(out, warmupMicrosRegexp, Collections.<String>emptyList()));
         }
-        if (options.getWarmupMode().isBulk()) {
+        if (options.getWarmupMode().orElse(Defaults.DEFAULT_WARMUP_MODE).isBulk()) {
             warmupBenches.addAll(benchmarks);
         }
 
@@ -259,7 +260,7 @@
             if (params.getForks() > 0) {
                 ActionPlan r = new ActionPlan();
                 r.mixIn(base);
-                if (options.getWarmupMode().isIndi()) {
+                if (options.getWarmupMode().orElse(Defaults.DEFAULT_WARMUP_MODE).isIndi()) {
                     r.addWarmupMeasurement(br);
                 } else {
                     r.addMeasurement(br);
@@ -379,7 +380,7 @@
 
             if (ecode != 0) {
                 out.println("WARNING: Forked process returned code: " + ecode);
-                if (options.shouldFailOnError()) {
+                if (options.shouldFailOnError().orElse(Defaults.SHOULD_FAIL_ON_ERROR)) {
                     throw new IllegalStateException("WARNING: Forked process returned code: " + ecode);
                 }
             }
@@ -409,13 +410,7 @@
         boolean isOnWindows = osName.contains("indows");
         String platformSpecificBinaryPostfix = isOnWindows ? ".exe" : "";
 
-        String classPath;
-
-        if (options.getJvmClassPath() != null) {
-            classPath = options.getJvmClassPath();
-        } else {
-            classPath = (String) props.get("java.class.path");
-        }
+        String classPath = options.getJvmClassPath().orElse((String) props.get("java.class.path"));
 
         if (isOnWindows) {
             classPath = '"' + classPath + '"';
@@ -424,8 +419,8 @@
         List<String> command = new ArrayList<String>();
 
         // use supplied jvm if given
-        if (options.getJvm() != null) {
-            command.add(options.getJvm());
+        if (options.getJvm().hasValue()) {
+            command.add(options.getJvm().get());
         } else {
             // else find out which one parent is and use that
             StringBuilder javaExecutable = new StringBuilder();
@@ -438,8 +433,8 @@
             command.add(javaExecutable.toString());
         }
 
-        if (options.getJvmArgs() != null) { // use supplied jvm args if given in cmd line
-            command.addAll(Arrays.asList(options.getJvmArgs().split("[ ]+")));
+        if (options.getJvmArgs().hasValue()) { // use supplied jvm args if given in cmd line
+            command.addAll(Arrays.asList(options.getJvmArgs().get().split("[ ]+")));
         } else if (annJvmArgs != null) { // use jvm args supplied in annotation which shuns implicit args
             command.addAll(Arrays.asList(annJvmArgs.split("[ ]+")));
         } else {
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java	Mon Jan 13 20:10:37 2014 +0400
@@ -39,8 +39,8 @@
 import org.openjdk.jmh.runner.options.handlers.ThreadsOptionHandler;
 import org.openjdk.jmh.runner.options.handlers.TimeUnitOptionHandler;
 import org.openjdk.jmh.runner.options.handlers.TimeValueOptionHandler;
-import org.openjdk.jmh.runner.parameters.Defaults;
 import org.openjdk.jmh.runner.parameters.TimeValue;
+import org.openjdk.jmh.util.internal.Optional;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -77,43 +77,43 @@
      */
 
     @Option(name = "-i", aliases = {"--iterations"}, metaVar = "INT", usage = "Number of iterations.")
-    protected int iterations = -1;
+    protected Integer iterations;
 
-    @Option(name = "-r", aliases = {"--runtime"}, metaVar = "TIME", usage = "Run time for each iteration. Examples: 100s, 200ms; defaults to " + Defaults.MEASUREMENT_TIME_SECS + "s", handler = TimeValueOptionHandler.class)
-    protected TimeValue runTime = null;
+    @Option(name = "-r", aliases = {"--runtime"}, metaVar = "TIME", usage = "Run time for each iteration. Examples: 100s, 200ms", handler = TimeValueOptionHandler.class)
+    protected TimeValue runTime;
 
     @Option(name = "-wi", aliases = {"--warmupiterations"}, metaVar = "INT", usage = "Number of warmup iterations to run.")
-    protected int warmupIterations = -1;
+    protected Integer warmupIterations;
 
-    @Option(name = "-w", aliases = {"--warmup"}, metaVar = "TIME", usage = "Run time for warmup iterations. Result not used when calculating score. Examples 100s, 200ms; defaults to " + Defaults.WARMUP_TIME_SECS + "", handler = TimeValueOptionHandler.class)
-    protected TimeValue warmupTime = null;
+    @Option(name = "-w", aliases = {"--warmup"}, metaVar = "TIME", usage = "Run time for warmup iterations. Result not used when calculating score. Examples 100s, 200ms", handler = TimeValueOptionHandler.class)
+    protected TimeValue warmupTime;
 
     @Option(name = "-bm", aliases = {"--mode"}, multiValued = false, metaVar = "MODE", usage = "Benchmark mode", handler = BenchmarkModeTypeOptionHandler.class)
-    protected List<Mode> benchMode = null;
+    protected List<Mode> benchMode = new ArrayList<Mode>();
 
     @Option(name = "-t", aliases = {"--threads"}, usage = "Number of threads to run the microbenchmark with. Special value \"max\" will use Runtime.availableProcessors()", handler = ThreadsOptionHandler.class)
-    protected int threads = Integer.MIN_VALUE;
+    protected Integer threads;
 
     @Option(name = "-tg", aliases = {"--threadGroups"}, usage = "Thread group distribution", handler = ThreadCountsOptionHandler.class)
     protected List<Integer> threadGroups = new ArrayList<Integer>();
 
-    @Option(name = "-si", aliases = {"--synciterations"}, usage = "Should the harness continue to load each thread with work untill all threads are done with their measured work? Default is " + Defaults.SHOULD_SYNCH_ITERATIONS, handler = BooleanOptionHandler.class)
-    protected Boolean synchIterations = null; // true
+    @Option(name = "-si", aliases = {"--synciterations"}, usage = "Should the harness continue to load each thread with work untill all threads are done with their measured work?", handler = BooleanOptionHandler.class)
+    protected Boolean synchIterations;
 
     @Option(name = "-gc", usage = "Should do System.gc() between iterations?", handler = BooleanOptionHandler.class)
-    protected boolean gcEachIteration = false;
+    protected Boolean gcEachIteration;
 
     @Option(name = "-v", aliases = {"--verbosity"}, metaVar = "LEVEL", usage = "Verbosity mode: (silent, normal, extra)")
-    protected VerboseMode verbose = VerboseMode.NORMAL;
+    protected VerboseMode verbose;
 
     @Option(name = "-foe", usage = "Fail the harness on benchmark erro?", handler = BooleanOptionHandler.class)
-    protected boolean failOnError = false;
+    protected Boolean failOnError;
 
     @Option(name = "-prof", aliases = {"--useprofiler"}, multiValued = false, usage = "Use profilers for collecting additional info, use --listProfilers to list available profilers", handler = ProfilersOptionHandler.class)
     protected Set<ProfilerType> profilers = EnumSet.noneOf(ProfilerType.class);
 
     @Option(name = "-tu", aliases = {"--timeunit"}, usage = "Output time unit. Available values: m, s, ms, us, ns", handler = TimeUnitOptionHandler.class)
-    protected TimeUnit timeUnit = null;
+    protected TimeUnit timeUnit;
 
     // test selection options
     @Argument(metaVar = "REGEXP", usage = "Microbenchmarks to run. Regexp filtering out classes or methods which are MicroBenchmarks.")
@@ -122,34 +122,34 @@
     // micro options
 
     @Option(name = "-f", aliases = {"--fork"}, metaVar = "{ INT }", usage = "Start each benchmark in new JVM, forking from the same JDK unless --jvm is set. Optional parameter specifies number of times harness should fork. Zero forks means \"no fork\", also \"false\" is accepted", handler = ForkOptionHandler.class)
-    protected int fork = -1;
+    protected Integer fork;
 
     @Option(name = "-wf", aliases = {"--warmupfork"}, metaVar = "{ INT }", usage = "Number of warmup fork executions. (warmup fork execution results are ignored).")
-    protected int warmupFork = -1;
+    protected Integer warmupFork;
 
     @Option(name = "-o", aliases = {"--output"}, metaVar = "FILE", usage = "Redirect output to FILE")
-    protected String output = null;
+    protected String output;
 
     @Option(name = "-rff", aliases = {"--result"}, metaVar = "FILE", usage = "Redirect results to FILE")
-    protected String result = Defaults.RESULT_FILE;
+    protected String result;
 
     @Option(name = "-rf", aliases = {"--resultformat"}, metaVar = "FORMAT", usage = "Format to use for results, use --listResultFormats to list available formats")
-    protected ResultFormatType resultFormat = ResultFormatType.defaultType();
+    protected ResultFormatType resultFormat;
 
     @Option(name = "--jvm", metaVar = "JVM", usage = "Custom JVM to use with fork.")
-    protected String jvm = null;
+    protected String jvm;
 
     @Option(name = "--jvmargs", metaVar = "JVMARGS", usage = "Custom JVM arguments for --jvm, default is to use parent process's arguments")
-    protected String jvmArgs = null;
+    protected String jvmArgs;
 
     @Option(name = "--jvmclasspath", metaVar = "CLASSPATH", usage = "Custom classpath for --jvm, default is to use parent process's classpath")
-    protected String jvmClassPath = null;
+    protected String jvmClassPath;
 
     @Option(name = "-e", aliases = {"--exclude"}, multiValued = true, metaVar = "REGEXP", usage = "Microbenchmarks to exclude. Regexp filtering out classes or methods which are MicroBenchmarks.")
     protected List<String> excludes = new ArrayList<String>();
 
     @Option(name = "-wm", aliases = {"--warmupmode"}, usage = "Warmup mode for warming up selected micro benchmarks. Warmup modes are: BULK (before all benchmarks), INDI (before each benchmark), BULK_INDI (both)")
-    protected WarmupMode warmupMode = WarmupMode.defaultMode();
+    protected WarmupMode warmupMode;
 
     @Option(name = "-wmb", aliases = {"--warmupmicrobenchmarks"}, multiValued = true, metaVar = "REGEXP", usage = "Microbenchmarks to run for warmup before running any other benchmarks. These micros may be different from the target micros to warm up the harness or other parts of the JVM prior to running the target micro benchmarks. Regexp filtering out classes or methods which are MicroBenchmarks.")
     protected List<String> warmupMicros = new ArrayList<String>();
@@ -159,13 +159,13 @@
     protected boolean list = false;
 
     @Option(name = "--listResultFormats", usage = "List available result formats")
-    protected boolean listResultFormats = false;
+    protected boolean listResultFormats;
 
     @Option(name = "-h", aliases = {"--help"}, usage = "Display help")
     protected boolean help = false;
 
     @Option(name = "--listProfilers", usage = "List available profilers")
-    protected boolean listProfilers = false;
+    protected boolean listProfilers;
 
     /**
      * Kawaguchi's parser
@@ -207,8 +207,8 @@
      * @return the value
      */
     @Override
-    public WarmupMode getWarmupMode() {
-        return warmupMode;
+    public Optional<WarmupMode> getWarmupMode() {
+        return Optional.eitherOf(warmupMode);
     }
 
     /**
@@ -265,8 +265,8 @@
      * @return the value
      */
     @Override
-    public String getJvm() {
-        return jvm;
+    public Optional<String> getJvm() {
+        return Optional.eitherOf(jvm);
     }
 
     /**
@@ -275,8 +275,8 @@
      * @return the value
      */
     @Override
-    public String getJvmArgs() {
-        return jvmArgs;
+    public Optional<String> getJvmArgs() {
+        return Optional.eitherOf(jvmArgs);
     }
 
     /**
@@ -285,8 +285,8 @@
      * @return the value
      */
     @Override
-    public String getJvmClassPath() {
-        return jvmClassPath;
+    public Optional<String> getJvmClassPath() {
+        return Optional.eitherOf(jvmClassPath);
     }
 
     /**
@@ -295,8 +295,8 @@
      * @return the value
      */
     @Override
-    public int getForkCount() {
-        return fork;
+    public Optional<Integer> getForkCount() {
+        return Optional.eitherOf(fork);
     }
 
     /**
@@ -305,8 +305,8 @@
      * @return the value
      */
     @Override
-    public int getWarmupForkCount() {
-        return warmupFork;
+    public Optional<Integer> getWarmupForkCount() {
+        return Optional.eitherOf(warmupFork);
     }
 
     /**
@@ -315,18 +315,18 @@
      * @return the value
      */
     @Override
-    public String getOutput() {
-        return output;
+    public Optional<String> getOutput() {
+        return Optional.eitherOf(output);
     }
 
     @Override
-    public ResultFormatType getResultFormat() {
-        return resultFormat;
+    public Optional<ResultFormatType> getResultFormat() {
+        return Optional.eitherOf(resultFormat);
     }
 
     @Override
-    public String getResult() {
-        return result;
+    public Optional<String> getResult() {
+        return Optional.eitherOf(result);
     }
 
     public boolean shouldListResultFormats() {
@@ -358,8 +358,8 @@
      * @return the value
      */
     @Override
-    public int getMeasurementIterations() {
-        return iterations;
+    public Optional<Integer> getMeasurementIterations() {
+        return Optional.eitherOf(iterations);
     }
 
     /**
@@ -368,8 +368,8 @@
      * @return the value
      */
     @Override
-    public TimeValue getMeasurementTime() {
-        return runTime;
+    public Optional<TimeValue> getMeasurementTime() {
+        return Optional.eitherOf(runTime);
     }
 
     /**
@@ -378,8 +378,8 @@
      * @return the value
      */
     @Override
-    public TimeValue getWarmupTime() {
-        return warmupTime;
+    public Optional<TimeValue> getWarmupTime() {
+        return Optional.eitherOf(warmupTime);
     }
 
     /**
@@ -388,8 +388,8 @@
      * @return the value
      */
     @Override
-    public int getWarmupIterations() {
-        return warmupIterations;
+    public Optional<Integer> getWarmupIterations() {
+        return Optional.eitherOf(warmupIterations);
     }
 
     /**
@@ -398,20 +398,20 @@
      * @return the value
      */
     @Override
-    public int getThreads() {
-        return threads;
+    public Optional<Integer> getThreads() {
+        return Optional.eitherOf(threads);
     }
 
     @Override
-    public int[] getThreadGroups() {
+    public Optional<int[]> getThreadGroups() {
         if (threadGroups.isEmpty()) {
-            return new int[] { 1 };
+            return Optional.none();
         } else {
             int[] r = new int[threadGroups.size()];
             for (int c = 0; c < r.length; c++) {
                 r[c] = threadGroups.get(c);
             }
-            return r;
+            return Optional.of(r);
         }
     }
 
@@ -421,8 +421,8 @@
      * @return the value
      */
     @Override
-    public boolean shouldDoGC() {
-        return gcEachIteration;
+    public Optional<Boolean> shouldDoGC() {
+        return Optional.eitherOf(gcEachIteration);
     }
 
     /**
@@ -431,8 +431,8 @@
      * @return the value
      */
     @Override
-    public Boolean shouldSyncIterations() {
-        return synchIterations;
+    public Optional<Boolean> shouldSyncIterations() {
+        return Optional.eitherOf(synchIterations);
     }
 
     /**
@@ -441,8 +441,8 @@
      * @return the value
      */
     @Override
-    public VerboseMode verbosity() {
-        return verbose;
+    public Optional<VerboseMode> verbosity() {
+        return Optional.eitherOf(verbose);
     }
 
     /**
@@ -451,8 +451,8 @@
      * @return the value
      */
     @Override
-    public TimeUnit getTimeUnit() {
-        return timeUnit;
+    public Optional<TimeUnit> getTimeUnit() {
+        return Optional.eitherOf(timeUnit);
     }
 
     /**
@@ -460,8 +460,8 @@
      * @return the value
      */
     @Override
-    public boolean shouldFailOnError() {
-        return failOnError;
+    public Optional<Boolean> shouldFailOnError() {
+        return Optional.eitherOf(failOnError);
     }
 
     /**
@@ -475,7 +475,7 @@
 
     @Override
     public Collection<Mode> getBenchModes() {
-        return (benchMode == null) ? null : new HashSet<Mode>(benchMode);
+        return new HashSet<Mode>(benchMode);
     }
 
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java	Mon Jan 13 20:10:37 2014 +0400
@@ -28,6 +28,7 @@
 import org.openjdk.jmh.output.results.ResultFormatType;
 import org.openjdk.jmh.profile.ProfilerType;
 import org.openjdk.jmh.runner.parameters.TimeValue;
+import org.openjdk.jmh.util.internal.Optional;
 
 import java.io.Serializable;
 import java.util.Collection;
@@ -50,31 +51,31 @@
 
     /**
      * Which file to use for dumping the output
-     * @return file name; null if not defined
+     * @return file name
      */
-    String getOutput();
+    Optional<String> getOutput();
 
     /**
      * Result format to use
      * @return format type
      */
-    ResultFormatType getResultFormat();
+    Optional<ResultFormatType> getResultFormat();
 
     /**
      * Which file to use for dumping the result
-     * @return file name; null if not defined
+     * @return file name
      */
-    String getResult();
+    Optional<String> getResult();
 
     /**
      * Should force GC between iterations?
      * @return should GC?
      */
-    boolean shouldDoGC();
+    Optional<Boolean> shouldDoGC();
 
     /**
      * Profilers to use for the run.
-     * @return profilers to use; empty set if no profilers are required
+     * @return profilers to use; empty collection if no profilers are required
      */
     Collection<ProfilerType> getProfilers();
 
@@ -82,109 +83,108 @@
      * How verbose should we be?
      * @return verbosity mode
      */
-    VerboseMode verbosity();
+    Optional<VerboseMode> verbosity();
 
     /**
      * Should harness terminate on first error encountered?
      * @return should terminate?
      */
-    boolean shouldFailOnError();
+    Optional<Boolean> shouldFailOnError();
 
     /**
      * Number of threads to run
-     * @return number of threads; 0 to use maximum number of threads; -1 to use default
+     * @return number of threads; 0 to use maximum number of threads
      */
-    int getThreads();
+    Optional<Integer> getThreads();
 
     /**
      * Thread subgroups distribution.
      * @return array of thread ratios
      */
-    int[] getThreadGroups();
+    Optional<int[]> getThreadGroups();
 
     /**
      * Should synchronize iterations?
-     * TODO: Rework "null" interface?
-     * @return should we? "null" if not defined
+     * @return should we?
      */
-    Boolean shouldSyncIterations();
+    Optional<Boolean> shouldSyncIterations();
 
     /**
      * Number of warmup iterations
-     * @return number of warmup iterations; -1 to use default
+     * @return number of warmup iterations
      */
-    int getWarmupIterations();
+    Optional<Integer> getWarmupIterations();
 
     /**
      * The duration for warmup iterations
-     * @return duration; null, if use default
+     * @return duration
      */
-    TimeValue getWarmupTime();
+    Optional<TimeValue> getWarmupTime();
 
     /**
      * Warmup mode.
      * @return warmup mode
      */
-    WarmupMode getWarmupMode();
+    Optional<WarmupMode> getWarmupMode();
 
     /**
      * Which benchmarks to warmup before doing the run.
-     * @return list of regexps matching the relevant benchmarks; null if no benchmarks are defined
+     * @return list of regexps matching the relevant benchmarks; empty if no benchmarks are defined
      */
     List<String> getWarmupIncludes();
 
     /**
      * Number of measurement iterations
-     * @return number of measurement iterations; -1 to use default
+     * @return number of measurement iterations
      */
-    int getMeasurementIterations();
+    Optional<Integer> getMeasurementIterations();
 
     /**
      * The duration for measurement iterations
-     * @return duration; null, if use default
+     * @return duration
      */
-    TimeValue getMeasurementTime();
+    Optional<TimeValue> getMeasurementTime();
 
     /**
      * Benchmarks modes to execute.
-     * @return modes to execute the benchmarks in; null to use the default mode
+     * @return modes to execute the benchmarks in; empty to use the default modes
      */
     Collection<Mode> getBenchModes();
 
     /**
      * Timeunit to use in units.
-     * @return timeunit; null to use the default timeunit
+     * @return timeunit
      */
-    TimeUnit getTimeUnit();
+    Optional<TimeUnit> getTimeUnit();
 
     /**
      * Fork count
      * @return fork count; 0, to prohibit forking
      */
-    int getForkCount();
+    Optional<Integer> getForkCount();
 
     /**
      * Number of initial forks to ignore the results for
      * @return initial fork count; 0, to disable
      */
-    int getWarmupForkCount();
+    Optional<Integer> getWarmupForkCount();
 
     /**
      * Additional JVM classpath
      * @return additional JVM classpath to add to forked VM
      */
-    String getJvmClassPath();
+    Optional<String> getJvmClassPath();
 
     /**
      * JVM to use for forks
      * @return JVM binary location
      */
-    String getJvm();
+    Optional<String> getJvm();
 
     /**
      * JVM parameters to use with forks
      * @return JVM parameters
      */
-    String getJvmArgs();
+    Optional<String> getJvmArgs();
 
 }
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java	Mon Jan 13 20:10:37 2014 +0400
@@ -27,8 +27,8 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.output.results.ResultFormatType;
 import org.openjdk.jmh.profile.ProfilerType;
-import org.openjdk.jmh.runner.parameters.Defaults;
 import org.openjdk.jmh.runner.parameters.TimeValue;
+import org.openjdk.jmh.util.internal.Optional;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -90,61 +90,61 @@
 
     // ---------------------------------------------------------------------------
 
-    private String output;
+    private Optional<String> output = Optional.none();
 
     @Override
     public ChainedOptionsBuilder output(String filename) {
-        this.output = filename;
+        this.output = Optional.of(filename);
         return this;
     }
 
     @Override
-    public String getOutput() {
+    public Optional<String> getOutput() {
         return output;
     }
 
     // ---------------------------------------------------------------------------
 
-    private ResultFormatType rfType = ResultFormatType.defaultType();
+    private Optional<ResultFormatType> rfType = Optional.none();
 
     @Override
     public ChainedOptionsBuilder resultFormat(ResultFormatType type) {
-        rfType = type;
+        rfType = Optional.of(type);
         return this;
     }
 
     @Override
-    public ResultFormatType getResultFormat() {
+    public Optional<ResultFormatType> getResultFormat() {
         return rfType;
     }
 
     // ---------------------------------------------------------------------------
 
-    private String result = Defaults.RESULT_FILE;
+    private Optional<String> result = Optional.none();
 
     @Override
     public ChainedOptionsBuilder result(String filename) {
-        this.result = filename;
+        this.result = Optional.of(filename);
         return this;
     }
 
     @Override
-    public String getResult() {
+    public Optional<String> getResult() {
         return result;
     }
 
     // ---------------------------------------------------------------------------
 
-    private boolean shouldDoGC;
+    private Optional<Boolean> shouldDoGC = Optional.none();
 
     @Override
     public ChainedOptionsBuilder shouldDoGC(boolean value) {
-        shouldDoGC = value;
+        shouldDoGC = Optional.of(value);
         return this;
     }
 
     @Override
-    public boolean shouldDoGC() {
+    public Optional<Boolean> shouldDoGC() {
         return shouldDoGC;
     }
 
@@ -165,121 +165,121 @@
 
     // ---------------------------------------------------------------------------
 
-    private VerboseMode verbosity = VerboseMode.NORMAL;
+    private Optional<VerboseMode> verbosity = Optional.none();
 
     @Override
     public ChainedOptionsBuilder verbosity(VerboseMode mode) {
-        verbosity = mode;
+        verbosity = Optional.of(mode);
         return this;
     }
 
     @Override
-    public VerboseMode verbosity() {
+    public Optional<VerboseMode> verbosity() {
         return verbosity;
     }
 
     // ---------------------------------------------------------------------------
 
-    private boolean shouldFailOnError;
+    private Optional<Boolean> shouldFailOnError = Optional.none();
 
     @Override
     public ChainedOptionsBuilder shouldFailOnError(boolean value) {
-        shouldFailOnError = value;
+        shouldFailOnError = Optional.of(value);
         return this;
     }
 
     @Override
-    public boolean shouldFailOnError() {
+    public Optional<Boolean> shouldFailOnError() {
         return shouldFailOnError;
     }
 
     // ---------------------------------------------------------------------------
 
-    private int threads = Integer.MIN_VALUE;
+    private Optional<Integer> threads = Optional.none();
 
     @Override
     public ChainedOptionsBuilder threads(int count) {
-        this.threads = count;
+        this.threads = Optional.of(count);
         return this;
     }
 
     @Override
-    public int getThreads() {
+    public Optional<Integer> getThreads() {
         return threads;
     }
 
     // ---------------------------------------------------------------------------
 
-    private int[] threadGroups = new int[] {1};
+    private Optional<int[]> threadGroups = Optional.none();
 
     @Override
     public ChainedOptionsBuilder threadGroups(int... groups) {
-        this.threadGroups = groups;
+        this.threadGroups = Optional.of(groups);
         return this;
     }
 
     @Override
-    public int[] getThreadGroups() {
+    public Optional<int[]> getThreadGroups() {
         return threadGroups;
     }
 
     // ---------------------------------------------------------------------------
 
-    private Boolean syncIterations;
+    private Optional<Boolean> syncIterations = Optional.none();
 
     @Override
     public ChainedOptionsBuilder syncIterations(boolean value) {
-        this.syncIterations = value;
+        this.syncIterations = Optional.of(value);
         return this;
     }
 
     @Override
-    public Boolean shouldSyncIterations() {
+    public Optional<Boolean> shouldSyncIterations() {
         return syncIterations;
     }
 
     // ---------------------------------------------------------------------------
 
-    private int warmupIterations = -1;
+    private Optional<Integer> warmupIterations = Optional.none();
 
     @Override
     public ChainedOptionsBuilder warmupIterations(int value) {
-        this.warmupIterations = value;
+        this.warmupIterations = Optional.of(value);
         return this;
     }
 
     @Override
-    public int getWarmupIterations() {
+    public Optional<Integer> getWarmupIterations() {
         return warmupIterations;
     }
 
     // ---------------------------------------------------------------------------
 
-    private TimeValue warmupTime;
+    private Optional<TimeValue> warmupTime = Optional.none();
 
     @Override
     public ChainedOptionsBuilder warmupTime(TimeValue value) {
-        this.warmupTime = value;
+        this.warmupTime = Optional.of(value);
         return this;
     }
 
     @Override
-    public TimeValue getWarmupTime() {
+    public Optional<TimeValue> getWarmupTime() {
         return warmupTime;
     }
 
     // ---------------------------------------------------------------------------
 
-    private WarmupMode warmupMode = WarmupMode.defaultMode();
+    private Optional<WarmupMode> warmupMode = Optional.none();
 
     @Override
     public ChainedOptionsBuilder warmupMode(WarmupMode mode) {
-        this.warmupMode = mode;
+        this.warmupMode = Optional.of(mode);
         return this;
     }
 
     @Override
-    public WarmupMode getWarmupMode() {
+    public Optional<WarmupMode> getWarmupMode() {
         return warmupMode;
     }
 
@@ -300,43 +300,40 @@
 
     // ---------------------------------------------------------------------------
 
-    private int iterations = -1;
+    private Optional<Integer> iterations = Optional.none();
 
     @Override
     public ChainedOptionsBuilder measurementIterations(int count) {
-        this.iterations = count;
+        this.iterations = Optional.of(count);
         return this;
     }
 
     @Override
-    public int getMeasurementIterations() {
+    public Optional<Integer> getMeasurementIterations() {
         return iterations;
     }
 
     // ---------------------------------------------------------------------------
 
-    private TimeValue measurementTime;
+    private Optional<TimeValue> measurementTime = Optional.none();
 
     @Override
     public ChainedOptionsBuilder measurementTime(TimeValue value) {
-        this.measurementTime = value;
+        this.measurementTime = Optional.of(value);
         return this;
     }
 
     @Override
-    public TimeValue getMeasurementTime() {
+    public Optional<TimeValue> getMeasurementTime() {
         return measurementTime;
     }
 
     // ---------------------------------------------------------------------------
 
-    private EnumSet<Mode> benchModes;
+    private EnumSet<Mode> benchModes = EnumSet.noneOf(Mode.class);
 
     @Override
     public ChainedOptionsBuilder mode(Mode mode) {
-        if (benchModes == null) {
-            benchModes = EnumSet.noneOf(Mode.class);
-        }
         benchModes.add(mode);
         return this;
     }
@@ -348,91 +345,91 @@
 
     // ---------------------------------------------------------------------------
 
-    private TimeUnit timeUnit;
+    private Optional<TimeUnit> timeUnit = Optional.none();
 
     @Override
     public ChainedOptionsBuilder timeUnit(TimeUnit tu) {
-        this.timeUnit = tu;
+        this.timeUnit = Optional.of(tu);
         return this;
     }
 
     @Override
-    public TimeUnit getTimeUnit() {
+    public Optional<TimeUnit> getTimeUnit() {
         return timeUnit;
     }
 
     // ---------------------------------------------------------------------------
 
-    private int forks = -1;
+    private Optional<Integer> forks = Optional.none();
 
     @Override
     public ChainedOptionsBuilder forks(int value) {
-        this.forks = value;
+        this.forks = Optional.of(value);
         return this;
     }
 
     @Override
-    public int getForkCount() {
+    public Optional<Integer> getForkCount() {
         return forks;
     }
 
     // ---------------------------------------------------------------------------
 
-    private int warmupForks = -1;
+    private Optional<Integer> warmupForks = Optional.none();
 
     @Override
     public ChainedOptionsBuilder warmupForks(int value) {
-        this.warmupForks = value;
+        this.warmupForks = Optional.of(value);
         return this;
     }
 
     @Override
-    public int getWarmupForkCount() {
+    public Optional<Integer> getWarmupForkCount() {
         return warmupForks;
     }
 
     // ---------------------------------------------------------------------------
 
-    private String jvmClassPath;
+    private Optional<String> jvmClassPath = Optional.none();
 
     @Override
     public ChainedOptionsBuilder jvmClasspath(String value) {
-        this.jvmClassPath = value;
+        this.jvmClassPath = Optional.of(value);
         return this;
     }
 
     @Override
-    public String getJvmClassPath() {
+    public Optional<String> getJvmClassPath() {
         return jvmClassPath;
     }
 
     // ---------------------------------------------------------------------------
 
-    private String jvmBinary;
+    private Optional<String> jvmBinary = Optional.none();
 
     @Override
     public ChainedOptionsBuilder jvm(String path) {
-        this.jvmBinary = path;
+        this.jvmBinary = Optional.of(path);
         return this;
     }
 
     @Override
-    public String getJvm() {
+    public Optional<String> getJvm() {
         return jvmBinary;
     }
 
     // ---------------------------------------------------------------------------
 
-    private String jvmArgs;
+    private Optional<String> jvmArgs = Optional.none();
 
     @Override
     public ChainedOptionsBuilder jvmArgs(String value) {
-        this.jvmArgs = value;
+        this.jvmArgs = Optional.of(value);
         return this;
     }
 
     @Override
-    public String getJvmArgs() {
+    public Optional<String> getJvmArgs() {
         return jvmArgs;
     }
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/BenchmarkParams.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/BenchmarkParams.java	Mon Jan 13 20:10:37 2014 +0400
@@ -29,13 +29,10 @@
 import org.openjdk.jmh.annotations.Threads;
 import org.openjdk.jmh.runner.ActionMode;
 import org.openjdk.jmh.runner.BenchmarkRecord;
-import org.openjdk.jmh.runner.MicroBenchmarkHandlers;
 import org.openjdk.jmh.runner.options.Options;
-import org.openjdk.jmh.util.ClassUtils;
 import org.openjdk.jmh.util.Utils;
 
 import java.io.Serializable;
-import java.lang.reflect.Method;
 import java.util.Arrays;
 
 public class BenchmarkParams implements Serializable {
@@ -48,30 +45,6 @@
     private final IterationParams warmup;
     private final IterationParams measurement;
 
-    private int decideForks(int optionForks, int benchForks) {
-        if (optionForks == -1) {
-            if (benchForks == -1) {
-                return Defaults.DEFAULT_FORK_TIMES;
-            } else {
-                return benchForks;
-            }
-        } else {
-            return optionForks;
-        }
-    }
-
-    private int decideWarmupForks(int optionWarmupForks, int benchWarmupForks) {
-        if (optionWarmupForks == -1) {
-            if (benchWarmupForks == -1) {
-                return Defaults.DEFAULT_WARMUP_FORK_TIMES;
-            } else {
-                return benchWarmupForks;
-            }
-        } else {
-            return optionWarmupForks;
-        }
-    }
-
     /**
      * Test entry method
      */
@@ -86,15 +59,20 @@
     }
 
     public BenchmarkParams(Options options, BenchmarkRecord benchmark, ActionMode mode) {
-        this.threadGroups = decideThreadGroups(options.getThreadGroups(), benchmark.getThreadGroups());
+        this.threadGroups = options.getThreadGroups().orElse(benchmark.getThreadGroups());
 
-        int threads = options.getThreads() > Integer.MIN_VALUE ? options.getThreads() : benchmark.getThreads().orElse(Defaults.THREADS);
+        int threads = options.getThreads().orElse(
+                benchmark.getThreads().orElse(
+                        Defaults.THREADS));
+
         if (threads == Threads.MAX) {
             threads = Runtime.getRuntime().availableProcessors();
         }
+
         this.threads = Utils.roundUp(threads, Utils.sum(threadGroups));
 
-        this.synchIterations = getBoolean(options.shouldSyncIterations(), Defaults.SHOULD_SYNCH_ITERATIONS);
+        this.synchIterations = options.shouldSyncIterations().orElse(
+                Defaults.SHOULD_SYNCH_ITERATIONS);
 
         this.measurement = mode.doMeasurement() ?
                 getMeasurement(options, benchmark) :
@@ -104,49 +82,41 @@
                 getWarmup(options, benchmark) :
                 new IterationParams(this, 0, TimeValue.NONE);
 
-        this.forks = decideForks(options.getForkCount(), benchmark.getForks().orElse(Defaults.DEFAULT_FORK_TIMES));
-        this.warmupForks = decideWarmupForks(options.getWarmupForkCount(), benchmark.getWarmupForks().orElse(Defaults.DEFAULT_WARMUP_FORK_TIMES));
+        this.forks = options.getForkCount().orElse(
+                benchmark.getForks().orElse(
+                        Defaults.DEFAULT_FORK_TIMES));
+
+        this.warmupForks = options.getWarmupForkCount().orElse(
+                benchmark.getWarmupForks().orElse(
+                        Defaults.DEFAULT_WARMUP_FORK_TIMES));
     }
 
     private IterationParams getWarmup(Options options, BenchmarkRecord benchmark) {
-        boolean isSingleShot = (benchmark.getMode() == Mode.SingleShotTime);
-        int iters = benchmark.getWarmupIterations().orElse(-1);
-        if (isSingleShot) {
-            return new IterationParams(
-                    this,
-                    getInteger(options.getWarmupIterations(), iters, Defaults.SINGLE_SHOT_WARMUP_COUNT),
-                    TimeValue.NONE);
-        } else {
-            TimeValue timeValue = options.getWarmupTime();
-            if (timeValue == null || timeValue.getTime() == -1) {
-                timeValue = benchmark.getWarmupTime().orElse(Defaults.WARMUP_TIME);
-            }
-            return new IterationParams(
-                    this,
-                    getInteger(options.getWarmupIterations(), iters, Defaults.WARMUP_ITERATION_COUNT),
-                    timeValue);
-        }
+        return new IterationParams(
+                this,
+                options.getWarmupIterations().orElse(
+                        benchmark.getWarmupIterations().orElse(
+                            (benchmark.getMode() == Mode.SingleShotTime) ? Defaults.SINGLE_SHOT_WARMUP_COUNT : Defaults.WARMUP_ITERATION_COUNT
+                )),
+                options.getWarmupTime().orElse(
+                        benchmark.getWarmupTime().orElse(
+                            (benchmark.getMode() == Mode.SingleShotTime) ? TimeValue.NONE : Defaults.WARMUP_TIME
+                ))
+        );
     }
 
     private IterationParams getMeasurement(Options options, BenchmarkRecord benchmark) {
-        boolean isSingleShot = (benchmark.getMode() == Mode.SingleShotTime);
-        int iters = benchmark.getMeasurementIterations().orElse(-1);
-        if (isSingleShot) {
-            return new IterationParams(
-                    this,
-                    getInteger(options.getMeasurementIterations(), iters, Defaults.SINGLE_SHOT_ITERATION_COUNT),
-                    TimeValue.NONE);
-
-        } else {
-            TimeValue timeValue = options.getMeasurementTime();
-            if (timeValue == null || timeValue.getTime() == -1) {
-                timeValue = benchmark.getMeasurementTime().orElse(Defaults.ITERATION_TIME);
-            }
-            return new IterationParams(
-                    this,
-                    getInteger(options.getMeasurementIterations(), iters, Defaults.MEASUREMENT_ITERATION_COUNT),
-                    timeValue);
-        }
+        return new IterationParams(
+                this,
+                options.getMeasurementIterations().orElse(
+                        benchmark.getMeasurementIterations().orElse(
+                                (benchmark.getMode() == Mode.SingleShotTime) ? Defaults.SINGLE_SHOT_ITERATION_COUNT : Defaults.MEASUREMENT_ITERATION_COUNT
+                        )),
+                options.getMeasurementTime().orElse(
+                        benchmark.getMeasurementTime().orElse(
+                                (benchmark.getMode() == Mode.SingleShotTime) ? TimeValue.NONE : Defaults.ITERATION_TIME
+                        ))
+        );
     }
 
     public boolean shouldSynchIterations() {
@@ -207,20 +177,4 @@
         return result;
     }
 
-    private static int[] decideThreadGroups(int[] first, int[] second) {
-        if (first.length == 1 && first[0] == 1) {
-            return second;
-        } else {
-            return first;
-        }
-    }
-
-    private static boolean getBoolean(Boolean value, boolean defaultValue) {
-        return value == null ? defaultValue : value;
-    }
-
-    private static int getInteger(int first, int second, int third) {
-        return first >= 0 ? first : (second >= 0 ? second : third);
-    }
-
 }
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/Defaults.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/Defaults.java	Mon Jan 13 20:10:37 2014 +0400
@@ -24,6 +24,10 @@
  */
 package org.openjdk.jmh.runner.parameters;
 
+import org.openjdk.jmh.output.results.ResultFormatType;
+import org.openjdk.jmh.runner.options.VerboseMode;
+import org.openjdk.jmh.runner.options.WarmupMode;
+
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -56,4 +60,9 @@
     public static final boolean SHOULD_SYNCH_ITERATIONS = true;
 
     public static final String RESULT_FILE = "jmh.out";
+    public static final VerboseMode DEFAULT_VERBOSITY = VerboseMode.NORMAL;
+    public static final Boolean SHOULD_FAIL_ON_ERROR = false;
+    public static final WarmupMode DEFAULT_WARMUP_MODE = WarmupMode.INDI;
+    public static final ResultFormatType RESULT_FORMAT = ResultFormatType.NONE;
+    public static final Boolean SHOULD_DO_GC = false;
 }
--- a/jmh-core/src/main/java/org/openjdk/jmh/util/internal/Optional.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/util/internal/Optional.java	Mon Jan 13 20:10:37 2014 +0400
@@ -85,6 +85,18 @@
         }
     }
 
+    public static <T> Optional<T> eitherOf(T val) {
+        if (val == null) {
+            return Optional.none();
+        } else {
+            return Optional.of(val);
+        }
+    }
+
+    public boolean hasValue() {
+        return val != null;
+    }
+
     public String toString() {
         if (val == null) {
             return "[]";
@@ -100,6 +112,23 @@
         return val;
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Optional optional = (Optional) o;
+
+        if (val != null ? !val.equals(optional.val) : optional.val != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return val != null ? val.hashCode() : 0;
+    }
+
     public interface Extractor<T> {
         T valueOf(String s);
     }
--- a/jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestOptions.java	Mon Jan 13 15:42:59 2014 +0400
+++ b/jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestOptions.java	Mon Jan 13 20:10:37 2014 +0400
@@ -243,7 +243,7 @@
 
     @Test
     public void testThreadGroups_Default() throws Exception {
-        Assert.assertArrayEquals(EMPTY_BUILDER.getThreadGroups(), EMPTY_CMDLINE.getThreadGroups());
+        Assert.assertEquals(EMPTY_BUILDER.getThreadGroups(), EMPTY_CMDLINE.getThreadGroups());
     }
 
     @Test