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