• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.checkArgument;
20 import static com.google.common.collect.Lists.newArrayList;
21 import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
22 import static com.google.common.util.concurrent.Futures.immediateFuture;
23 import static com.google.common.util.concurrent.FuturesGetChecked.checkExceptionClassValidity;
24 import static com.google.common.util.concurrent.FuturesGetChecked.classValueValidator;
25 import static com.google.common.util.concurrent.FuturesGetChecked.getChecked;
26 import static com.google.common.util.concurrent.FuturesGetChecked.isCheckedException;
27 import static com.google.common.util.concurrent.FuturesGetChecked.weakSetValidator;
28 
29 import com.google.caliper.BeforeExperiment;
30 import com.google.caliper.Benchmark;
31 import com.google.caliper.Param;
32 import com.google.common.collect.ImmutableSet;
33 import com.google.common.util.concurrent.FuturesGetChecked.GetCheckedTypeValidator;
34 import java.io.IOException;
35 import java.net.URISyntaxException;
36 import java.security.GeneralSecurityException;
37 import java.security.KeyException;
38 import java.util.List;
39 import java.util.TooManyListenersException;
40 import java.util.concurrent.BrokenBarrierException;
41 import java.util.concurrent.ExecutionException;
42 import java.util.concurrent.Future;
43 import java.util.concurrent.TimeoutException;
44 import java.util.prefs.BackingStoreException;
45 import java.util.prefs.InvalidPreferencesFormatException;
46 import java.util.zip.DataFormatException;
47 import javax.security.auth.RefreshFailedException;
48 
49 /** Microbenchmark for {@link Futures#getChecked}. */
50 public class FuturesGetCheckedBenchmark {
51   private enum Validator {
52     NON_CACHING_WITH_CONSTRUCTOR_CHECK(nonCachingWithConstructorCheckValidator()),
53     NON_CACHING_WITHOUT_CONSTRUCTOR_CHECK(nonCachingWithoutConstructorCheckValidator()),
54     WEAK_SET(weakSetValidator()),
55     CLASS_VALUE(classValueValidator()),
56     ;
57 
58     final GetCheckedTypeValidator validator;
59 
Validator(GetCheckedTypeValidator validator)60     Validator(GetCheckedTypeValidator validator) {
61       this.validator = validator;
62     }
63   }
64 
65   private enum Result {
66     SUCCESS(immediateFuture(new Object())),
67     FAILURE(immediateFailedFuture(new Exception()));
68 
69     final Future<Object> future;
70 
Result(Future<Object> result)71     Result(Future<Object> result) {
72       this.future = result;
73     }
74   }
75 
76   private enum ExceptionType {
77     CHECKED(IOException.class),
78     UNCHECKED(RuntimeException.class);
79 
80     final Class<? extends Exception> exceptionType;
81 
ExceptionType(Class<? extends Exception> exceptionType)82     ExceptionType(Class<? extends Exception> exceptionType) {
83       this.exceptionType = exceptionType;
84     }
85   }
86 
87   private static final ImmutableSet<Class<? extends Exception>> OTHER_EXCEPTION_TYPES =
88       ImmutableSet.of(
89           BackingStoreException.class,
90           BrokenBarrierException.class,
91           CloneNotSupportedException.class,
92           DataFormatException.class,
93           ExecutionException.class,
94           GeneralSecurityException.class,
95           InvalidPreferencesFormatException.class,
96           KeyException.class,
97           RefreshFailedException.class,
98           TimeoutException.class,
99           TooManyListenersException.class,
100           URISyntaxException.class);
101 
102   @Param Validator validator;
103   @Param Result result;
104   @Param ExceptionType exceptionType;
105   /**
106    * The number of other exception types in the cache of known-good exceptions and the number of
107    * other {@code ClassValue} entries for the exception type to be tested. This lets us evaluate
108    * whether our solution scales to use with multiple exception types and to whether it is affected
109    * by other {@code ClassValue} users. Some of the benchmarked implementations don't use one or
110    * both of these mechanisms, so they will be unaffected.
111    */
112   @Param({"0", "1", "12"})
113   int otherEntriesInDataStructure;
114 
115   final List<ClassValue<?>> retainedReferencesToOtherClassValues = newArrayList();
116 
117   @BeforeExperiment
addOtherEntries()118   void addOtherEntries() throws Exception {
119     GetCheckedTypeValidator validator = this.validator.validator;
120     Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
121 
122     for (Class<? extends Exception> exceptionClass :
123         OTHER_EXCEPTION_TYPES.asList().subList(0, otherEntriesInDataStructure)) {
124       getChecked(validator, immediateFuture(""), exceptionClass);
125     }
126 
127     for (int i = 0; i < otherEntriesInDataStructure; i++) {
128       ClassValue<Boolean> classValue =
129           new ClassValue<Boolean>() {
130             @Override
131             protected Boolean computeValue(Class<?> type) {
132               return true;
133             }
134           };
135       classValue.get(exceptionType);
136       retainedReferencesToOtherClassValues.add(classValue);
137     }
138   }
139 
140   @Benchmark
benchmarkGetChecked(int reps)141   int benchmarkGetChecked(int reps) {
142     int tmp = 0;
143     GetCheckedTypeValidator validator = this.validator.validator;
144     Future<Object> future = this.result.future;
145     Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
146     for (int i = 0; i < reps; ++i) {
147       try {
148         tmp += getChecked(validator, future, exceptionType).hashCode();
149       } catch (Exception e) {
150         tmp += e.hashCode();
151       }
152     }
153     return tmp;
154   }
155 
nonCachingWithoutConstructorCheckValidator()156   private static GetCheckedTypeValidator nonCachingWithoutConstructorCheckValidator() {
157     return NonCachingWithoutConstructorCheckValidator.INSTANCE;
158   }
159 
160   private enum NonCachingWithoutConstructorCheckValidator implements GetCheckedTypeValidator {
161     INSTANCE;
162 
163     @Override
validateClass(Class<? extends Exception> exceptionClass)164     public void validateClass(Class<? extends Exception> exceptionClass) {
165       checkArgument(
166           isCheckedException(exceptionClass),
167           "Futures.getChecked exception type (%s) must not be a RuntimeException",
168           exceptionClass);
169     }
170   }
171 
nonCachingWithConstructorCheckValidator()172   private static GetCheckedTypeValidator nonCachingWithConstructorCheckValidator() {
173     return NonCachingWithConstructorCheckValidator.INSTANCE;
174   }
175 
176   private enum NonCachingWithConstructorCheckValidator implements GetCheckedTypeValidator {
177     INSTANCE;
178 
179     @Override
validateClass(Class<? extends Exception> exceptionClass)180     public void validateClass(Class<? extends Exception> exceptionClass) {
181       checkExceptionClassValidity(exceptionClass);
182     }
183   }
184 }
185