• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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