1 /* 2 * Copyright (C) 2014 The Guava Authors 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.common.util.concurrent; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.caliper.Benchmark; 22 import com.google.caliper.Param; 23 import com.google.caliper.api.VmOptions; 24 import com.google.common.collect.ImmutableList; 25 26 import java.util.concurrent.Callable; 27 import java.util.concurrent.CancellationException; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.Executor; 30 31 /** 32 * A benchmark for {@link Futures#combine} 33 */ 34 @VmOptions({"-Xms12g", "-Xmx12g", "-d64"}) 35 public class FuturesCombineBenchmark { 36 37 enum Impl { 38 OLD { combine(final Callable<V> combiner, Executor executor, Iterable<? extends ListenableFuture<?>> futures)39 @Override <V> ListenableFuture<V> combine(final Callable<V> combiner, Executor executor, 40 Iterable<? extends ListenableFuture<?>> futures) { 41 ListenableFuture<?> trigger = Futures.successfulAsList(futures); 42 checkNotNull(combiner); 43 checkNotNull(trigger); 44 return Futures.transform(trigger, new AsyncFunction<Object, V>() { 45 @Override public ListenableFuture<V> apply(Object arg) throws Exception { 46 try { 47 return Futures.immediateFuture(combiner.call()); 48 } catch (CancellationException e) { 49 return Futures.immediateCancelledFuture(); 50 } catch (ExecutionException e) { 51 return Futures.immediateFailedFuture(e.getCause()); // OK to rethrow on Error 52 } 53 } 54 }, executor); 55 } 56 }, 57 NEW { 58 @Override 59 <V> ListenableFuture<V> combine(Callable<V> combiner, final Executor executor, 60 Iterable<? extends ListenableFuture<?>> futures) { 61 return Futures.combine(combiner, executor, futures); 62 } 63 }; 64 65 abstract <V> ListenableFuture<V> combine( 66 Callable<V> combiner, Executor executor, 67 Iterable<? extends ListenableFuture<?>> futures); 68 } 69 70 private static final Executor INLINE_EXECUTOR = new Executor() { 71 @Override public void execute(Runnable command) { 72 command.run(); 73 } 74 }; 75 76 @Param Impl impl; 77 @Param({"1", "5", "10"}) int numInputs; 78 79 @Benchmark int timeDoneSuccesfulFutures(int reps) throws Exception { 80 ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder(); 81 for (int i = 0; i < numInputs; i++) { 82 futuresBuilder.add(Futures.immediateFuture(i)); 83 } 84 ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build(); 85 Impl impl = this.impl; 86 Callable<Integer> callable = Callables.returning(12); 87 int sum = 0; 88 for (int i = 0; i < reps; i++) { 89 sum += impl.combine(callable, INLINE_EXECUTOR, futures).get(); 90 } 91 return sum; 92 } 93 94 @Benchmark int timeDoneFailedFutures(int reps) throws Exception { 95 ImmutableList.Builder<ListenableFuture<?>> futuresBuilder = ImmutableList.builder(); 96 for (int i = 0; i < numInputs; i++) { 97 futuresBuilder.add(Futures.immediateFailedFuture(new Exception("boom"))); 98 } 99 ImmutableList<ListenableFuture<?>> futures = futuresBuilder.build(); 100 Impl impl = this.impl; 101 Callable<Integer> callable = Callables.returning(12); 102 int sum = 0; 103 for (int i = 0; i < reps; i++) { 104 sum += impl.combine(callable, INLINE_EXECUTOR, futures).get(); 105 } 106 return sum; 107 } 108 109 @Benchmark int timeSuccesfulFutures(int reps) throws Exception { 110 Impl impl = this.impl; 111 Callable<Integer> callable = Callables.returning(12); 112 int sum = 0; 113 for (int i = 0; i < reps; i++) { 114 ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList(); 115 ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures); 116 for (SettableFuture<Integer> future : futures) { 117 future.set(i); 118 } 119 sum += combined.get(); 120 } 121 return sum; 122 } 123 124 @Benchmark int timeFailedFutures(int reps) throws Exception { 125 Impl impl = this.impl; 126 Callable<Integer> callable = Callables.returning(12); 127 int sum = 0; 128 Exception throwable = new Exception("boom"); 129 for (int i = 0; i < reps; i++) { 130 ImmutableList<SettableFuture<Integer>> futures = getSettableFutureList(); 131 ListenableFuture<Integer> combined = impl.combine(callable, INLINE_EXECUTOR, futures); 132 for (SettableFuture<Integer> future : futures) { 133 future.setException(throwable); 134 } 135 sum += combined.get(); 136 } 137 return sum; 138 } 139 140 private ImmutableList<SettableFuture<Integer>> getSettableFutureList() { 141 ImmutableList.Builder<SettableFuture<Integer>> futuresBuilder = ImmutableList.builder(); 142 for (int i = 0; i < numInputs; i++) { 143 futuresBuilder.add(SettableFuture.<Integer>create()); 144 } 145 return futuresBuilder.build(); 146 } 147 } 148