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