Home | History | Annotate | Download | only in concurrent
      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 {
     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