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