1 /* 2 * Copyright (C) 2011 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.caliper.runner; 18 19 import com.google.caliper.runner.Instrument.Instrumentation; 20 import com.google.common.base.Function; 21 import com.google.common.collect.FluentIterable; 22 import com.google.common.collect.ImmutableMap; 23 import com.google.common.collect.ImmutableSet; 24 import com.google.common.collect.ImmutableSetMultimap; 25 import com.google.common.collect.Lists; 26 import com.google.common.collect.SetMultimap; 27 import com.google.common.collect.Sets; 28 29 import java.util.Collection; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.Set; 33 34 import javax.inject.Inject; 35 36 /** 37 * A set of {@link Experiment experiments} constructed by taking all possible combinations of 38 * instruments, benchmark methods, user parameters, VM specs and VM arguments. 39 */ 40 public final class FullCartesianExperimentSelector implements ExperimentSelector { 41 private ImmutableSet<Instrumentation> instrumentations; 42 private final ImmutableSet<VirtualMachine> vms; 43 private final ImmutableSetMultimap<String, String> userParameters; 44 45 @Inject FullCartesianExperimentSelector( 46 ImmutableSet<Instrumentation> instrumentations, 47 ImmutableSet<VirtualMachine> vms, 48 @BenchmarkParameters ImmutableSetMultimap<String, String> userParameters) { 49 this.instrumentations = instrumentations; 50 this.vms = vms; 51 this.userParameters = userParameters; 52 } 53 54 // TODO(gak): put this someplace more sensible 55 @Override public ImmutableSet<Instrument> instruments() { 56 return FluentIterable.from(instrumentations) 57 .transform(new Function<Instrumentation, Instrument>() { 58 @Override public Instrument apply(Instrumentation input) { 59 return input.instrument(); 60 } 61 }) 62 .toSet(); 63 } 64 65 @Override public ImmutableSet<VirtualMachine> vms() { 66 return vms; 67 } 68 69 @Override public ImmutableSetMultimap<String, String> userParameters() { 70 return userParameters; 71 } 72 73 @Override public ImmutableSet<Experiment> selectExperiments() { 74 List<Experiment> experiments = Lists.newArrayList(); 75 for (Instrumentation instrumentation : instrumentations) { 76 for (VirtualMachine vm : vms) { 77 for (List<String> userParamsChoice : cartesian(userParameters)) { 78 ImmutableMap<String, String> theseUserParams = 79 zip(userParameters.keySet(), userParamsChoice); 80 experiments.add(new Experiment(instrumentation, theseUserParams, vm)); 81 } 82 } 83 } 84 return ImmutableSet.copyOf(experiments); 85 } 86 87 protected static <T> Set<List<T>> cartesian(SetMultimap<String, T> multimap) { 88 @SuppressWarnings({"unchecked", "rawtypes"}) // promised by spec 89 ImmutableMap<String, Set<T>> paramsAsMap = (ImmutableMap) multimap.asMap(); 90 return Sets.cartesianProduct(paramsAsMap.values().asList()); 91 } 92 93 protected static <K, V> ImmutableMap<K, V> zip(Set<K> keys, Collection<V> values) { 94 ImmutableMap.Builder<K, V> builder = ImmutableMap.builder(); 95 96 Iterator<K> keyIterator = keys.iterator(); 97 Iterator<V> valueIterator = values.iterator(); 98 99 while (keyIterator.hasNext() && valueIterator.hasNext()) { 100 builder.put(keyIterator.next(), valueIterator.next()); 101 } 102 103 if (keyIterator.hasNext() || valueIterator.hasNext()) { 104 throw new AssertionError(); // I really screwed up, then. 105 } 106 return builder.build(); 107 } 108 109 @Override public String selectionType() { 110 return "Full cartesian product"; 111 } 112 } 113