• 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.acl.NotOwnerException;
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     final GetCheckedTypeValidator validator;
58 
Validator(GetCheckedTypeValidator validator)59     Validator(GetCheckedTypeValidator validator) {
60       this.validator = validator;
61     }
62   }
63 
64   private enum Result {
65     SUCCESS(immediateFuture(new Object())),
66     FAILURE(immediateFailedFuture(new Exception()));
67 
68     final Future<Object> future;
69 
Result(Future<Object> result)70     Result(Future<Object> result) {
71       this.future = result;
72     }
73   }
74 
75   private enum ExceptionType {
76     CHECKED(IOException.class),
77     UNCHECKED(RuntimeException.class);
78 
79     final Class<? extends Exception> exceptionType;
80 
ExceptionType(Class<? extends Exception> exceptionType)81     ExceptionType(Class<? extends Exception> exceptionType) {
82       this.exceptionType = exceptionType;
83     }
84   }
85 
86   private static final ImmutableSet<Class<? extends Exception>> OTHER_EXCEPTION_TYPES =
87       ImmutableSet.of(
88           BackingStoreException.class,
89           BrokenBarrierException.class,
90           CloneNotSupportedException.class,
91           DataFormatException.class,
92           ExecutionException.class,
93           GeneralSecurityException.class,
94           InvalidPreferencesFormatException.class,
95           NotOwnerException.class,
96           RefreshFailedException.class,
97           TimeoutException.class,
98           TooManyListenersException.class,
99           URISyntaxException.class);
100 
101   @Param Validator validator;
102   @Param Result result;
103   @Param ExceptionType exceptionType;
104   /**
105    * The number of other exception types in the cache of known-good exceptions and the number of
106    * other {@code ClassValue} entries for the exception type to be tested. This lets us evaluate
107    * whether our solution scales to use with multiple exception types and to whether it is affected
108    * by other {@code ClassValue} users. Some of the benchmarked implementations don't use one or
109    * both of these mechanisms, so they will be unaffected.
110    */
111   @Param({"0", "1", "12"})
112   int otherEntriesInDataStructure;
113 
114   final List<ClassValue<?>> retainedReferencesToOtherClassValues = newArrayList();
115 
116   @BeforeExperiment
addOtherEntries()117   void addOtherEntries() throws Exception {
118     GetCheckedTypeValidator validator = this.validator.validator;
119     Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
120 
121     for (Class<? extends Exception> exceptionClass :
122         OTHER_EXCEPTION_TYPES.asList().subList(0, otherEntriesInDataStructure)) {
123       getChecked(validator, immediateFuture(""), exceptionClass);
124     }
125 
126     for (int i = 0; i < otherEntriesInDataStructure; i++) {
127       ClassValue<Boolean> classValue =
128           new ClassValue<Boolean>() {
129             @Override
130             protected Boolean computeValue(Class<?> type) {
131               return true;
132             }
133           };
134       classValue.get(exceptionType);
135       retainedReferencesToOtherClassValues.add(classValue);
136     }
137   }
138 
139   @Benchmark
benchmarkGetChecked(int reps)140   int benchmarkGetChecked(int reps) {
141     int tmp = 0;
142     GetCheckedTypeValidator validator = this.validator.validator;
143     Future<Object> future = this.result.future;
144     Class<? extends Exception> exceptionType = this.exceptionType.exceptionType;
145     for (int i = 0; i < reps; ++i) {
146       try {
147         tmp += getChecked(validator, future, exceptionType).hashCode();
148       } catch (Exception e) {
149         tmp += e.hashCode();
150       }
151     }
152     return tmp;
153   }
154 
nonCachingWithoutConstructorCheckValidator()155   private static GetCheckedTypeValidator nonCachingWithoutConstructorCheckValidator() {
156     return NonCachingWithoutConstructorCheckValidator.INSTANCE;
157   }
158 
159   private enum NonCachingWithoutConstructorCheckValidator implements GetCheckedTypeValidator {
160     INSTANCE;
161 
162     @Override
validateClass(Class<? extends Exception> exceptionClass)163     public void validateClass(Class<? extends Exception> exceptionClass) {
164       checkArgument(
165           isCheckedException(exceptionClass),
166           "Futures.getChecked exception type (%s) must not be a RuntimeException",
167           exceptionClass);
168     }
169   }
170 
nonCachingWithConstructorCheckValidator()171   private static GetCheckedTypeValidator nonCachingWithConstructorCheckValidator() {
172     return NonCachingWithConstructorCheckValidator.INSTANCE;
173   }
174 
175   private enum NonCachingWithConstructorCheckValidator implements GetCheckedTypeValidator {
176     INSTANCE;
177 
178     @Override
validateClass(Class<? extends Exception> exceptionClass)179     public void validateClass(Class<? extends Exception> exceptionClass) {
180       checkExceptionClassValidity(exceptionClass);
181     }
182   }
183 }
184