| /* |
| * Copyright (C) 2015 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.util.concurrent; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| import static com.google.common.collect.Lists.newArrayList; |
| import static com.google.common.util.concurrent.Futures.immediateFailedFuture; |
| import static com.google.common.util.concurrent.Futures.immediateFuture; |
| import static com.google.common.util.concurrent.FuturesGetChecked.checkExceptionClassValidity; |
| import static com.google.common.util.concurrent.FuturesGetChecked.classValueValidator; |
| import static com.google.common.util.concurrent.FuturesGetChecked.getChecked; |
| import static com.google.common.util.concurrent.FuturesGetChecked.isCheckedException; |
| import static com.google.common.util.concurrent.FuturesGetChecked.weakSetValidator; |
| |
| import com.google.caliper.BeforeExperiment; |
| import com.google.caliper.Benchmark; |
| import com.google.caliper.Param; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.util.concurrent.FuturesGetChecked.GetCheckedTypeValidator; |
| import java.io.IOException; |
| import java.net.URISyntaxException; |
| import java.security.GeneralSecurityException; |
| import java.security.acl.NotOwnerException; |
| import java.util.List; |
| import java.util.TooManyListenersException; |
| import java.util.concurrent.BrokenBarrierException; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Future; |
| import java.util.concurrent.TimeoutException; |
| import java.util.prefs.BackingStoreException; |
| import java.util.prefs.InvalidPreferencesFormatException; |
| import java.util.zip.DataFormatException; |
| import javax.security.auth.RefreshFailedException; |
| |
| /** Microbenchmark for {@link Futures#getChecked}. */ |
| public class FuturesGetCheckedBenchmark { |
| private enum Validator { |
| NON_CACHING_WITH_CONSTRUCTOR_CHECK(nonCachingWithConstructorCheckValidator()), |
| NON_CACHING_WITHOUT_CONSTRUCTOR_CHECK(nonCachingWithoutConstructorCheckValidator()), |
| WEAK_SET(weakSetValidator()), |
| CLASS_VALUE(classValueValidator()); |
| |
| final GetCheckedTypeValidator validator; |
| |
| Validator(GetCheckedTypeValidator validator) { |
| this.validator = validator; |
| } |
| } |
| |
| private enum Result { |
| SUCCESS(immediateFuture(new Object())), |
| FAILURE(immediateFailedFuture(new Exception())); |
| |
| final Future<Object> future; |
| |
| Result(Future<Object> result) { |
| this.future = result; |
| } |
| } |
| |
| private enum ExceptionType { |
| CHECKED(IOException.class), |
| UNCHECKED(RuntimeException.class); |
| |
| final Class<? extends Exception> exceptionType; |
| |
| ExceptionType(Class<? extends Exception> exceptionType) { |
| this.exceptionType = exceptionType; |
| } |
| } |
| |
| private static final ImmutableSet<Class<? extends Exception>> OTHER_EXCEPTION_TYPES = |
| ImmutableSet.of( |
| BackingStoreException.class, |
| BrokenBarrierException.class, |
| CloneNotSupportedException.class, |
| DataFormatException.class, |
| ExecutionException.class, |
| GeneralSecurityException.class, |
| InvalidPreferencesFormatException.class, |
| NotOwnerException.class, |
| RefreshFailedException.class, |
| TimeoutException.class, |
| TooManyListenersException.class, |
| URISyntaxException.class); |
| |
| @Param Validator validator; |
| @Param Result result; |
| @Param ExceptionType exceptionType; |
| /** |
| * The number of other exception types in the cache of known-good exceptions and the number of |
| * other {@code ClassValue} entries for the exception type to be tested. This lets us evaluate |
| * whether our solution scales to use with multiple exception types and to whether it is affected |
| * by other {@code ClassValue} users. Some of the benchmarked implementations don't use one or |
| * both of these mechanisms, so they will be unaffected. |
| */ |
| @Param({"0", "1", "12"}) |
| int otherEntriesInDataStructure; |
| |
| final List<ClassValue<?>> retainedReferencesToOtherClassValues = newArrayList(); |
| |
| @BeforeExperiment |
| void addOtherEntries() throws Exception { |
| GetCheckedTypeValidator validator = this.validator.validator; |
| Class<? extends Exception> exceptionType = this.exceptionType.exceptionType; |
| |
| for (Class<? extends Exception> exceptionClass : |
| OTHER_EXCEPTION_TYPES.asList().subList(0, otherEntriesInDataStructure)) { |
| getChecked(validator, immediateFuture(""), exceptionClass); |
| } |
| |
| for (int i = 0; i < otherEntriesInDataStructure; i++) { |
| ClassValue<Boolean> classValue = |
| new ClassValue<Boolean>() { |
| @Override |
| protected Boolean computeValue(Class<?> type) { |
| return true; |
| } |
| }; |
| classValue.get(exceptionType); |
| retainedReferencesToOtherClassValues.add(classValue); |
| } |
| } |
| |
| @Benchmark |
| int benchmarkGetChecked(int reps) { |
| int tmp = 0; |
| GetCheckedTypeValidator validator = this.validator.validator; |
| Future<Object> future = this.result.future; |
| Class<? extends Exception> exceptionType = this.exceptionType.exceptionType; |
| for (int i = 0; i < reps; ++i) { |
| try { |
| tmp += getChecked(validator, future, exceptionType).hashCode(); |
| } catch (Exception e) { |
| tmp += e.hashCode(); |
| } |
| } |
| return tmp; |
| } |
| |
| private static GetCheckedTypeValidator nonCachingWithoutConstructorCheckValidator() { |
| return NonCachingWithoutConstructorCheckValidator.INSTANCE; |
| } |
| |
| private enum NonCachingWithoutConstructorCheckValidator implements GetCheckedTypeValidator { |
| INSTANCE; |
| |
| @Override |
| public void validateClass(Class<? extends Exception> exceptionClass) { |
| checkArgument( |
| isCheckedException(exceptionClass), |
| "Futures.getChecked exception type (%s) must not be a RuntimeException", |
| exceptionClass); |
| } |
| } |
| |
| private static GetCheckedTypeValidator nonCachingWithConstructorCheckValidator() { |
| return NonCachingWithConstructorCheckValidator.INSTANCE; |
| } |
| |
| private enum NonCachingWithConstructorCheckValidator implements GetCheckedTypeValidator { |
| INSTANCE; |
| |
| @Override |
| public void validateClass(Class<? extends Exception> exceptionClass) { |
| checkExceptionClassValidity(exceptionClass); |
| } |
| } |
| } |