diff -r 734a9b2a1965 jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ProfilerTest.java
--- a/jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ProfilerTest.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/profilers/ProfilerTest.java	Tue Jan 13 18:29:06 2015 +0300
@@ -39,6 +39,7 @@
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 
+import java.util.Collection;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -72,14 +73,14 @@
 
     @Test
     public void testInternal_CLI() throws RunnerException, CommandLineOptionException {
-        Set<Class<? extends Profiler>> ps = new CommandLineOptions("-prof", "itinternal").getProfilers();
+        Collection<Class<? extends Profiler>> ps = new CommandLineOptions("-prof", "itinternal").getProfilers().get();
         Assert.assertEquals(1, ps.size());
         Assert.assertEquals(ItInternalProfiler.class.getName(), ps.iterator().next().getName());
     }
 
     @Test
     public void testExternal_CLI() throws RunnerException, CommandLineOptionException {
-        Set<Class<? extends Profiler>> ps = new CommandLineOptions("-prof", "itexternal").getProfilers();
+        Collection<Class<? extends Profiler>> ps = new CommandLineOptions("-prof", "itexternal").getProfilers().get();
         Assert.assertEquals(1, ps.size());
         Assert.assertEquals(ItExternalProfiler.class.getName(), ps.iterator().next().getName());
     }
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/annotations/AttachProfiler.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/annotations/AttachProfiler.java	Tue Jan 13 18:29:06 2015 +0300
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.annotations;
+
+import org.openjdk.jmh.profile.Profiler;
+
+public @interface AttachProfiler {
+
+    Class<? extends Profiler>[] value();
+
+}
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Tue Jan 13 18:29:06 2015 +0300
@@ -199,7 +199,8 @@
                                 group.getParams(),
                                 group.getOutputTimeUnit(),
                                 group.getOperationsPerInvocation(),
-                                group.getTimeout()
+                                group.getTimeout(),
+                                group.getProfilers()
                         );
 
                         if (entries.contains(br)) {
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java	Tue Jan 13 18:29:06 2015 +0300
@@ -24,6 +24,7 @@
  */
 package org.openjdk.jmh.generators.core;
 
+import org.openjdk.jmh.annotations.AttachProfiler;
 import org.openjdk.jmh.annotations.Fork;
 import org.openjdk.jmh.annotations.Measurement;
 import org.openjdk.jmh.annotations.Mode;
@@ -33,6 +34,7 @@
 import org.openjdk.jmh.annotations.Threads;
 import org.openjdk.jmh.annotations.Timeout;
 import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.Optional;
 
@@ -42,6 +44,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -257,6 +260,18 @@
         return Optional.none();
     }
 
+    public Optional<Collection<String>> getProfilers() {
+        AttachProfiler ann = getFinal(AttachProfiler.class);
+        if (ann != null) {
+            Collection<String> names = new ArrayList<String>();
+            for (Class<? extends Profiler> c : ann.value()) {
+                names.add(c.getCanonicalName());
+            }
+            return Optional.of(names);
+        }
+        return Optional.none();
+    }
+
     private <T extends Annotation> T getFinal(Class<T> annClass) {
         T finalAnn = null;
         for (MethodInvocation mi : methods) {
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/infra/BenchmarkParams.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/infra/BenchmarkParams.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/infra/BenchmarkParams.java	Tue Jan 13 18:29:06 2015 +0300
@@ -27,6 +27,7 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.annotations.Scope;
 import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.runner.WorkloadParams;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.Utils;
@@ -76,13 +77,13 @@
                              Mode mode, WorkloadParams params,
                              TimeUnit timeUnit, int opsPerInvocation,
                              String jvm, Collection<String> jvmArgs,
-                             TimeValue timeout) {
+                             TimeValue timeout, Collection<Class<? extends Profiler>> profilers) {
         super(benchmark, generatedTarget, synchIterations,
                 threads, threadGroups, forks, warmupForks,
                 warmup, measurement,
                 mode, params,
                 timeUnit, opsPerInvocation,
-                jvm, jvmArgs, timeout);
+                jvm, jvmArgs, timeout, profilers);
     }
 }
 
@@ -96,14 +97,14 @@
                              Mode mode, WorkloadParams params,
                              TimeUnit timeUnit, int opsPerInvocation,
                              String jvm, Collection<String> jvmArgs,
-                             TimeValue timeout) {
+                             TimeValue timeout, Collection<Class<? extends Profiler>> profilers) {
         super(benchmark, generatedTarget, synchIterations,
                 threads, threadGroups, forks, warmupForks,
                 warmup, measurement,
                 mode, params,
                 timeUnit, opsPerInvocation,
                 jvm, jvmArgs,
-                timeout);
+                timeout, profilers);
     }
 
     public BenchmarkParamsL4(BenchmarkParams other) {
@@ -137,14 +138,14 @@
                              Mode mode, WorkloadParams params,
                              TimeUnit timeUnit, int opsPerInvocation,
                              String jvm, Collection<String> jvmArgs,
-                             TimeValue timeout) {
+                             TimeValue timeout, Collection<Class<? extends Profiler>> profilers) {
         super(benchmark, generatedTarget, synchIterations,
                 threads, threadGroups, forks, warmupForks,
                 warmup, measurement,
                 mode, params,
                 timeUnit, opsPerInvocation,
                 jvm, jvmArgs,
-                timeout);
+                timeout, profilers);
     }
 
     public BenchmarkParamsL3(BenchmarkParams other) {
@@ -194,6 +195,7 @@
     protected final String jvm;
     protected final Collection<String> jvmArgs;
     protected final TimeValue timeout;
+    protected final Collection<Class<? extends Profiler>> profilers;
 
     public BenchmarkParamsL2(String benchmark, String generatedTarget, boolean synchIterations,
                              int threads, int[] threadGroups, int forks, int warmupForks,
@@ -201,7 +203,7 @@
                              Mode mode, WorkloadParams params,
                              TimeUnit timeUnit, int opsPerInvocation,
                              String jvm, Collection<String> jvmArgs,
-                             TimeValue timeout) {
+                             TimeValue timeout, Collection<Class<? extends Profiler>> profilers) {
         this.benchmark = benchmark;
         this.generatedTarget = generatedTarget;
         this.synchIterations = synchIterations;
@@ -218,6 +220,7 @@
         this.jvm = jvm;
         this.jvmArgs = jvmArgs;
         this.timeout = timeout;
+        this.profilers = profilers;
     }
 
     public BenchmarkParamsL2(BenchmarkParams other) {
@@ -237,6 +240,7 @@
         this.jvm = other.jvm;
         this.jvmArgs = other.jvmArgs;
         this.timeout = other.timeout;
+        this.profilers = other.profilers;
     }
 
     /**
@@ -361,6 +365,10 @@
         return Collections.unmodifiableCollection(jvmArgs);
     }
 
+    public Collection<Class<? extends Profiler>> getProfilers() {
+        return profilers;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/ProfilerFactory.java	Tue Jan 13 18:29:06 2015 +0300
@@ -113,6 +113,24 @@
         return null;
     }
 
+    public static Collection<Class<? extends Profiler>> getProfilers(Collection<String> names) {
+        Collection<Class<? extends Profiler>> result = new ArrayList<Class<? extends Profiler>>();
+        for (String name : names) {
+            Class<? extends Profiler> c = getProfilerByName(name);
+            if (c != null) {
+                List<String> msgs = new ArrayList<String>();
+                if (checkSupport(c, msgs)) {
+                    result.add(c);
+                } else {
+                    throw new IllegalStateException("Profiler " + name + " is not supported, " + msgs);
+                }
+            } else {
+                throw new IllegalStateException("Profiler " + name + " is not found");
+            }
+        }
+        return result;
+    }
+
     public static Profiler prepareProfiler(Class<? extends Profiler> klass, VerboseMode verboseMode) {
         try {
             return klass.newInstance();
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/BaseBenchmarkHandler.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseBenchmarkHandler.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BaseBenchmarkHandler.java	Tue Jan 13 18:29:06 2015 +0300
@@ -62,7 +62,7 @@
     private final List<InternalProfiler> registeredProfilers;
 
     public BaseBenchmarkHandler(OutputFormat out, final Class<?> clazz, Options options, BenchmarkParams executionParams) {
-        this.registeredProfilers = createProfilers(options);
+        this.registeredProfilers = createProfilers(executionParams, options);
         this.instances = new ThreadLocal<Object>() {
             @Override
             protected Object initialValue() {
@@ -83,12 +83,22 @@
         }
     }
 
-    private static List<InternalProfiler> createProfilers(Options options) {
+    private static List<InternalProfiler> createProfilers(BenchmarkParams params, Options options) {
         List<InternalProfiler> list = new ArrayList<InternalProfiler>();
         // register the profilers
-        for (Class<? extends Profiler> prof : options.getProfilers()) {
-            if (!ProfilerFactory.isInternal(prof)) continue;
-            list.add((InternalProfiler) ProfilerFactory.prepareProfiler(prof, options.verbosity().orElse(Defaults.VERBOSITY)));
+        for (Class<? extends Profiler> p : params.getProfilers()) {
+            if (!ProfilerFactory.isInternal(p)) continue;
+
+            List<String> initMessages = new ArrayList<String>();
+            if (!ProfilerFactory.checkSupport(p, initMessages)) {
+                StringBuilder sb = new StringBuilder();
+                for (String im : initMessages) {
+                    sb.append(String.format("%5s %s\n", "", im));
+                }
+                throw new BenchmarkException(new IllegalStateException("The requested profiler (" + p.getName() + ") is not supported: \n" + sb.toString()));
+            }
+
+            list.add((InternalProfiler) ProfilerFactory.prepareProfiler(p, options.verbosity().orElse(Defaults.VERBOSITY)));
         }
         return list;
     }
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkListEntry.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkListEntry.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/BenchmarkListEntry.java	Tue Jan 13 18:29:06 2015 +0300
@@ -25,6 +25,8 @@
 package org.openjdk.jmh.runner;
 
 import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.profile.Profiler;
+import org.openjdk.jmh.profile.ProfilerFactory;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.Optional;
 import org.openjdk.jmh.util.Utils;
@@ -60,6 +62,7 @@
     private final Optional<TimeUnit> tu;
     private final Optional<Integer> opsPerInvocation;
     private final Optional<TimeValue> timeout;
+    private final Optional<Collection<String>> profilers;
 
     private WorkloadParams workloadParams;
 
@@ -69,7 +72,7 @@
                               Optional<Integer> forks, Optional<Integer> warmupForks,
                               Optional<String> jvm, Optional<Collection<String>> jvmArgs, Optional<Collection<String>> jvmArgsPrepend, Optional<Collection<String>> jvmArgsAppend,
                               Optional<Map<String, String[]>> params, Optional<TimeUnit> tu, Optional<Integer> opsPerInv,
-                              Optional<TimeValue> timeout) {
+                              Optional<TimeValue> timeout, Optional<Collection<String>> profilers) {
         this.userName = userName;
         this.generatedName = generatedName;
         this.mode = mode;
@@ -92,12 +95,13 @@
         this.tu = tu;
         this.opsPerInvocation = opsPerInv;
         this.timeout = timeout;
+        this.profilers = profilers;
     }
 
     public BenchmarkListEntry(String line) {
         String[] args = line.split(BR_SEPARATOR);
 
-        if (args.length != 21) {
+        if (args.length != 22) {
             throw new IllegalStateException("Mismatched format for the line: " + line);
         }
 
@@ -123,6 +127,7 @@
         this.tu = Optional.of(args[18], TIMEUNIT_UNMARSHALLER);
         this.opsPerInvocation = Optional.of(args[19], INTEGER_UNMARSHALLER);
         this.timeout = Optional.of(args[20], TIME_VALUE_UNMARSHALLER);
+        this.profilers = Optional.of(args[21], STRING_COLLECTION_UNMARSHALLER);
     }
 
     public BenchmarkListEntry(String userName, String generatedName, Mode mode) {
@@ -131,7 +136,7 @@
                 Optional.<Integer>none(), Optional.<Integer>none(),
                 Optional.<String>none(), Optional.<Collection<String>>none(), Optional.<Collection<String>>none(), Optional.<Collection<String>>none(),
                 Optional.<Map<String, String[]>>none(), Optional.<TimeUnit>none(), Optional.<Integer>none(),
-                Optional.<TimeValue>none());
+                Optional.<TimeValue>none(), Optional.<Collection<String>>none());
     }
 
     public String toLine() {
@@ -155,7 +160,7 @@
                 forks, warmupForks,
                 jvm, jvmArgs, jvmArgsPrepend, jvmArgsAppend,
                 params, tu, opsPerInvocation,
-                timeout);
+                timeout, profilers);
     }
 
     public BenchmarkListEntry cloneWith(WorkloadParams p) {
@@ -165,7 +170,7 @@
                 forks, warmupForks,
                 jvm, jvmArgs, jvmArgsPrepend, jvmArgsAppend,
                 params, tu, opsPerInvocation,
-                timeout);
+                timeout, profilers);
         br.workloadParams = p;
         return br;
     }
@@ -401,4 +406,13 @@
             return sb.toString();
         }
     };
+
+    public Optional<Collection<Class<? extends Profiler>>> getProfilers() {
+        if (profilers.hasValue()) {
+            return Optional.of(ProfilerFactory.getProfilers(profilers.get()));
+        } else {
+            return Optional.none();
+        }
+
+    }
 }
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java	Tue Jan 13 18:29:06 2015 +0300
@@ -25,11 +25,14 @@
 package org.openjdk.jmh.runner;
 
 import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.results.format.ResultFormatType;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.runner.options.VerboseMode;
 import org.openjdk.jmh.runner.options.WarmupMode;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -146,4 +149,6 @@
      * Default timeout.
      */
     public static final TimeValue TIMEOUT = TimeValue.minutes(10);
+
+    public static final Collection<Class<? extends Profiler>> PROFILERS = Collections.emptyList();
 }
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/Runner.java	Tue Jan 13 18:29:06 2015 +0300
@@ -45,6 +45,7 @@
 import org.openjdk.jmh.util.HashMultimap;
 import org.openjdk.jmh.util.InputStreamDrainer;
 import org.openjdk.jmh.util.Multimap;
+import org.openjdk.jmh.util.Optional;
 import org.openjdk.jmh.util.TreeMultimap;
 import org.openjdk.jmh.util.UnCloseablePrintStream;
 import org.openjdk.jmh.util.Utils;
@@ -220,17 +221,6 @@
     }
 
     private Collection<RunResult> internalRun() throws RunnerException {
-        for (Class<? extends Profiler> p : options.getProfilers()) {
-            List<String> initMessages = new ArrayList<String>();
-            if (!ProfilerFactory.checkSupport(p, initMessages)) {
-                StringBuilder sb = new StringBuilder();
-                for (String im : initMessages) {
-                    sb.append(String.format("%5s %s\n", "", im));
-                }
-                throw new RunnerException("The requested profiler (" + p.getName() + ") is not supported: \n" + sb.toString());
-            }
-        }
-
         // If user requested the result file in one way or the other, touch the result file,
         // and prepare to write it out after the run.
         String resultFile = null;
@@ -472,10 +462,13 @@
         TimeValue timeout = options.getTimeout().orElse(
                 benchmark.getTimeout().orElse(Defaults.TIMEOUT));
 
+        Collection<Class<? extends Profiler>> profilers = options.getProfilers().orElse(
+                benchmark.getProfilers().orElse(Defaults.PROFILERS));
+
         return new BenchmarkParams(benchmark.getUsername(), benchmark.generatedTarget(), synchIterations,
                 threads, threadGroups, forks, warmupForks,
                 warmup, measurement, benchmark.getMode(), benchmark.getWorkloadParams(), timeUnit, opsPerInvocation,
-                jvm, jvmArgs, timeout);
+                jvm, jvmArgs, timeout, profilers);
     }
 
     private List<WorkloadParams> explodeAllParams(BenchmarkListEntry br) throws RunnerException {
@@ -581,7 +574,7 @@
 
             List<String> javaInvokeOptions = new ArrayList<String>();
             List<String> javaOptions = new ArrayList<String>();
-            for (Class<? extends Profiler> p : options.getProfilers()) {
+            for (Class<? extends Profiler> p : params.getProfilers()) {
                 if (!ProfilerFactory.isExternal(p)) continue;
                 ExternalProfiler prof = (ExternalProfiler) ProfilerFactory.prepareProfiler(p, null);
                 profilers.add(prof);
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/CommandLineOptions.java	Tue Jan 13 18:29:06 2015 +0300
@@ -66,7 +66,7 @@
     private final Optional<Boolean> gcEachIteration;
     private final Optional<VerboseMode> verbose;
     private final Optional<Boolean> failOnError;
-    private final Set<Class<? extends Profiler>> profilers = new HashSet<Class<? extends Profiler>>();
+    private final Collection<Class<? extends Profiler>> profilers = new HashSet<Class<? extends Profiler>>();
     private final Optional<TimeUnit> timeUnit;
     private final Optional<Integer> opsPerInvocation;
     private final List<String> regexps = new ArrayList<String>();
@@ -671,8 +671,12 @@
     }
 
     @Override
-    public Set<Class<? extends Profiler>> getProfilers() {
-        return profilers;
+    public Optional<Collection<Class<? extends Profiler>>> getProfilers() {
+        if (profilers.isEmpty()) {
+            return Optional.none();
+        } else {
+            return Optional.of(profilers);
+        }
     }
 
     @Override
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/Options.java	Tue Jan 13 18:29:06 2015 +0300
@@ -76,7 +76,7 @@
      * Profilers to use for the run.
      * @return profilers to use; empty collection if no profilers are required
      */
-    Collection<Class<? extends Profiler>> getProfilers();
+    Optional<Collection<Class<? extends Profiler>>> getProfilers();
 
     /**
      * How verbose should we be?
diff -r 734a9b2a1965 jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java
--- a/jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/runner/options/OptionsBuilder.java	Tue Jan 13 18:29:06 2015 +0300
@@ -181,18 +181,22 @@
 
     // ---------------------------------------------------------------------------
 
-    private Set<Class<? extends Profiler>> profilers = new HashSet<Class<? extends Profiler>>();
+    private Optional<Collection<Class<? extends Profiler>>> profilers = Optional.none();
 
     @Override
     public ChainedOptionsBuilder addProfiler(Class<? extends Profiler> prof) {
-        this.profilers.add(prof);
+        if (!profilers.hasValue()) {
+            Collection<Class<? extends Profiler>> newList = new ArrayList<Class<? extends Profiler>>();
+            profilers = Optional.of(newList);
+        }
+        profilers.get().add(prof);
         return this;
     }
 
     @Override
-    public Set<Class<? extends Profiler>> getProfilers() {
+    public Optional<Collection<Class<? extends Profiler>>> getProfilers() {
         if (otherOptions != null) {
-            profilers.addAll(otherOptions.getProfilers());
+            return profilers.orAnother(otherOptions.getProfilers());
         }
         return profilers;
     }
diff -r 734a9b2a1965 jmh-core/src/test/java/org/openjdk/jmh/results/TestAggregateResult.java
--- a/jmh-core/src/test/java/org/openjdk/jmh/results/TestAggregateResult.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/test/java/org/openjdk/jmh/results/TestAggregateResult.java	Tue Jan 13 18:29:06 2015 +0300
@@ -29,6 +29,7 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.infra.BenchmarkParams;
 import org.openjdk.jmh.infra.IterationParams;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.runner.IterationType;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.Utils;
@@ -54,7 +55,7 @@
                         new IterationParams(IterationType.MEASUREMENT, 1, TimeValue.seconds(1), 1),
                         Mode.Throughput, null, TimeUnit.SECONDS, 1,
                         Utils.getCurrentJvm(), Collections.<String>emptyList(),
-                        TimeValue.days(1)),
+                        TimeValue.days(1), Collections.<Class<? extends Profiler>>emptyList()),
                 new IterationParams(IterationType.MEASUREMENT, 1, TimeValue.days(1), 1)
         );
         for (double d : values) {
diff -r 734a9b2a1965 jmh-core/src/test/java/org/openjdk/jmh/results/format/ResultFormatTest.java
--- a/jmh-core/src/test/java/org/openjdk/jmh/results/format/ResultFormatTest.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/test/java/org/openjdk/jmh/results/format/ResultFormatTest.java	Tue Jan 13 18:29:06 2015 +0300
@@ -29,6 +29,7 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.infra.BenchmarkParams;
 import org.openjdk.jmh.infra.IterationParams;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.results.BenchmarkResult;
 import org.openjdk.jmh.results.IterationResult;
 import org.openjdk.jmh.results.ResultRole;
@@ -83,7 +84,8 @@
                     TimeUnit.SECONDS, 1,
                     Utils.getCurrentJvm(),
                     Collections.<String>emptyList(),
-                    TimeValue.days(1));
+                    TimeValue.days(1),
+                    Collections.<Class<? extends Profiler>>emptyList());
 
             Collection<BenchmarkResult> benchmarkResults = new ArrayList<BenchmarkResult>();
             for (int f = 0; f < r.nextInt(10); f++) {
diff -r 734a9b2a1965 jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java
--- a/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/test/java/org/openjdk/jmh/runner/RunnerTest.java	Tue Jan 13 18:29:06 2015 +0300
@@ -28,6 +28,7 @@
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.infra.BenchmarkParams;
 import org.openjdk.jmh.infra.IterationParams;
+import org.openjdk.jmh.profile.Profiler;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 import org.openjdk.jmh.runner.options.TimeValue;
 import org.openjdk.jmh.util.FileUtils;
@@ -62,7 +63,7 @@
                 new IterationParams(IterationType.MEASUREMENT, 1, TimeValue.seconds(1), 1),
                 Mode.Throughput, null, TimeUnit.SECONDS, 1,
                 Utils.getCurrentJvm(), Collections.<String>emptyList(),
-                TimeValue.days(1));
+                TimeValue.days(1), Collections.<Class<? extends Profiler>>emptyList());
         String[] command = blade.getSeparateExecutionCommand(bp, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
@@ -91,7 +92,7 @@
                 new IterationParams(IterationType.MEASUREMENT, 1, TimeValue.seconds(1), 1),
                 Mode.Throughput, null, TimeUnit.SECONDS, 1,
                 Utils.getCurrentJvm(), Arrays.asList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints),
-                TimeValue.days(1));
+                TimeValue.days(1), Collections.<Class<? extends Profiler>>emptyList());
         String[] command = blade.getSeparateExecutionCommand(bp, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
@@ -125,7 +126,7 @@
                 Mode.Throughput, null, TimeUnit.SECONDS, 1,
                 Utils.getCurrentJvm(),
                 Arrays.asList(CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints1, CompilerHints.XX_COMPILE_COMMAND_FILE + tempHints2),
-                TimeValue.days(1));
+                TimeValue.days(1), Collections.<Class<? extends Profiler>>emptyList());
         String[] command = blade.getSeparateExecutionCommand(bp, DUMMY_HOST, DUMMY_PORT, Collections.<String>emptyList(), Collections.<String>emptyList());
 
         // expecting 1 compile command file
diff -r 734a9b2a1965 jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestParentOptions.java
--- a/jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestParentOptions.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-core/src/test/java/org/openjdk/jmh/runner/options/TestParentOptions.java	Tue Jan 13 18:29:06 2015 +0300
@@ -84,24 +84,24 @@
     public void testProfiler_Empty() throws Exception {
         Options parent = new OptionsBuilder().build();
         Options builder = new OptionsBuilder().parent(parent).build();
-        Assert.assertTrue(builder.getProfilers().isEmpty());
+        Assert.assertTrue(builder.getProfilers().hasValue());
     }
 
     @Test
     public void testProfiler_Parent() throws Exception {
         Options parent = new OptionsBuilder().addProfiler(ClassloaderProfiler.class).build();
         Options builder = new OptionsBuilder().parent(parent).build();
-        Assert.assertTrue(builder.getProfilers().size() == 1);
-        Assert.assertTrue(builder.getProfilers().contains(ClassloaderProfiler.class));
+        Assert.assertTrue(builder.getProfilers().get().size() == 1);
+        Assert.assertTrue(builder.getProfilers().get().contains(ClassloaderProfiler.class));
     }
 
     @Test
     public void testProfiler_Merge() throws Exception {
         Options parent = new OptionsBuilder().addProfiler(ClassloaderProfiler.class).build();
         Options builder = new OptionsBuilder().parent(parent).addProfiler(CompilerProfiler.class).build();
-        Assert.assertTrue(builder.getProfilers().size() == 2);
-        Assert.assertTrue(builder.getProfilers().contains(ClassloaderProfiler.class));
-        Assert.assertTrue(builder.getProfilers().contains(CompilerProfiler.class));
+        Assert.assertTrue(builder.getProfilers().get().size() == 2);
+        Assert.assertTrue(builder.getProfilers().get().contains(ClassloaderProfiler.class));
+        Assert.assertTrue(builder.getProfilers().get().contains(CompilerProfiler.class));
     }
 
     @Test
diff -r 734a9b2a1965 jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_01_HelloWorld.java
--- a/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_01_HelloWorld.java	Tue Jan 13 15:02:26 2015 +0300
+++ b/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_01_HelloWorld.java	Tue Jan 13 18:29:06 2015 +0300
@@ -30,7 +30,9 @@
  */
 package org.openjdk.jmh.samples;
 
+import org.openjdk.jmh.annotations.AttachProfiler;
 import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.profile.LinuxPerfAsmProfiler;
 import org.openjdk.jmh.runner.Runner;
 import org.openjdk.jmh.runner.RunnerException;
 import org.openjdk.jmh.runner.options.Options;
@@ -66,6 +68,7 @@
      */
 
     @Benchmark
+    @AttachProfiler(LinuxPerfAsmProfiler.class)
     public void wellHelloThere() {
         // this method was intentionally left blank.
     }
