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