mirror of https://github.com/apache/jclouds.git
[JCLOUD 301]: Make increased use of Invokable params cache
This patch moves the Invokable Parameter cache to Reflection2 and adds a convenience method for it to allow it to be shared by multiple callers. The subsequent ability of S3Utils to use this cache results in a ~40% improvement in performance for generating signed GETs and PUTs for S3. This commit also converts a few others calls to Invokable.getParameters() but the observed benefit from those was small in microbenchmarks.
This commit is contained in:
parent
962003bb0b
commit
6b8ee8b904
|
@ -22,15 +22,16 @@ import static com.google.common.collect.Iterables.any;
|
|||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.reflect.Reflection2;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.Bucket;
|
||||
import org.jclouds.s3.S3Client;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.reflect.Parameter;
|
||||
|
||||
/**
|
||||
|
@ -77,7 +78,7 @@ public class S3Utils {
|
|||
|
||||
String bucketName = null;
|
||||
|
||||
ImmutableList<Parameter> parameters = request.getInvocation().getInvokable().getParameters();
|
||||
List<Parameter> parameters = Reflection2.getInvokableParameters(request.getInvocation().getInvokable());
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
if (any(Arrays.asList(parameters.get(i).getAnnotations()), ANNOTATIONTYPE_BUCKET)) {
|
||||
bucketName = (String) request.getInvocation().getArgs().get(i);
|
||||
|
|
|
@ -195,6 +195,24 @@ public class Reflection2 {
|
|||
}
|
||||
});
|
||||
|
||||
private static final LoadingCache<Invokable<?, ?>, ImmutableList<Parameter>> invokableParamsCache =
|
||||
CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<Invokable<?, ?>, ImmutableList<Parameter>>() {
|
||||
@Override
|
||||
public ImmutableList<Parameter> load(Invokable<?, ?> invokable) {
|
||||
return invokable.getParameters();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the {@link Parameter}s associated with the given {@link Invokable}. This function is backed by a cache.
|
||||
*
|
||||
* @param invokable
|
||||
* The {@link Invokable} we want to get Parameters from
|
||||
*/
|
||||
public static List<Parameter> getInvokableParameters(final Invokable<?, ?> invokable) {
|
||||
return invokableParamsCache.getUnchecked(invokable);
|
||||
}
|
||||
|
||||
private static class TypeTokenAndParameterTypes {
|
||||
|
||||
protected TypeToken<?> type;
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.jclouds.predicates.Validator;
|
|||
import org.jclouds.reflect.Invocation;
|
||||
import org.jclouds.rest.annotations.ParamValidators;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.reflect.Parameter;
|
||||
|
@ -67,7 +66,7 @@ public class InputParamValidator {
|
|||
* @throws IllegalStateException
|
||||
* if validation failed
|
||||
*/
|
||||
public void validateMethodParametersOrThrow(Invocation invocation, ImmutableList<Parameter> parameters) {
|
||||
public void validateMethodParametersOrThrow(Invocation invocation, List<Parameter> parameters) {
|
||||
try {
|
||||
performMethodValidation(checkNotNull(invocation, "invocation"));
|
||||
performParameterValidation(invocation, checkNotNull(parameters, "parameters"));
|
||||
|
@ -105,7 +104,7 @@ public class InputParamValidator {
|
|||
* @param args
|
||||
* arguments that correspond to the array of annotations
|
||||
*/
|
||||
private void performParameterValidation(Invocation invocation, ImmutableList<Parameter> parameters) {
|
||||
private void performParameterValidation(Invocation invocation, List<Parameter> parameters) {
|
||||
for (Parameter param : parameters) {
|
||||
ParamValidators annotation = param.getAnnotation(ParamValidators.class);
|
||||
if (annotation == null)
|
||||
|
|
|
@ -38,6 +38,7 @@ import static org.jclouds.http.HttpUtils.filterOutContentHeaders;
|
|||
import static org.jclouds.http.HttpUtils.tryFindHttpMethod;
|
||||
import static org.jclouds.http.Uris.uriBuilder;
|
||||
import static org.jclouds.io.Payloads.newPayload;
|
||||
import static org.jclouds.reflect.Reflection2.getInvokableParameters;
|
||||
import static org.jclouds.util.Strings2.replaceTokens;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
@ -150,13 +151,6 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
private final GetAcceptHeaders getAcceptHeaders;
|
||||
private final Invocation caller;
|
||||
private final boolean stripExpectHeader;
|
||||
private static final LoadingCache<Invokable<?, ?>, ImmutableList<Parameter>> invokableParamsCache =
|
||||
CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<Invokable<?, ?>, ImmutableList<Parameter>>() {
|
||||
@Override
|
||||
public ImmutableList<Parameter> load(Invokable<?, ?> invokable) {
|
||||
return invokable.getParameters();
|
||||
}
|
||||
});
|
||||
|
||||
@Inject
|
||||
private RestAnnotationProcessor(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion,
|
||||
|
@ -186,7 +180,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
@Override
|
||||
public GeneratedHttpRequest apply(Invocation invocation) {
|
||||
checkNotNull(invocation, "invocation");
|
||||
inputParamValidator.validateMethodParametersOrThrow(invocation, invokableParamsCache.getUnchecked(invocation.getInvokable()));
|
||||
inputParamValidator.validateMethodParametersOrThrow(invocation, getInvokableParameters(invocation.getInvokable()));
|
||||
|
||||
Optional<URI> endpoint = Optional.absent();
|
||||
HttpRequest r = findOrNull(invocation.getArgs(), HttpRequest.class);
|
||||
|
@ -506,7 +500,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
|
||||
private static Collection<Parameter> parametersWithAnnotation(Invokable<?, ?> invokable,
|
||||
final Class<? extends Annotation> annotationType) {
|
||||
return filter(invokableParamsCache.getUnchecked(invokable), new Predicate<Parameter>() {
|
||||
return filter(getInvokableParameters(invokable), new Predicate<Parameter>() {
|
||||
public boolean apply(Parameter in) {
|
||||
return in.isAnnotationPresent(annotationType);
|
||||
}
|
||||
|
@ -609,7 +603,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
if (!argType.isArray() && parameterType.isArray()) {// TODO: &&
|
||||
// invocation.getInvokable().isVarArgs())
|
||||
// {
|
||||
int arrayLength = args.size() - invocation.getInvokable().getParameters().size() + 1;
|
||||
int arrayLength = args.size() - getInvokableParameters(invocation.getInvokable()).size() + 1;
|
||||
if (arrayLength == 0)
|
||||
break OUTER;
|
||||
arg = (Object[]) Array.newInstance(arg.getClass(), arrayLength);
|
||||
|
@ -631,7 +625,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
if (shouldBreak)
|
||||
break OUTER;
|
||||
} else {
|
||||
if (position + 1 == invocation.getInvokable().getParameters().size() && entry.getType().isArray())// TODO:
|
||||
if (position + 1 == getInvokableParameters(invocation.getInvokable()).size() && entry.getType().isArray())// TODO:
|
||||
// &&
|
||||
// invocation.getInvokable().isVarArgs())
|
||||
continue OUTER;
|
||||
|
@ -650,7 +644,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
@Override
|
||||
public Set<Integer> load(Invokable<?, ?> invokable) {
|
||||
Builder<Integer> toReturn = ImmutableSet.builder();
|
||||
for (Parameter param : invokable.getParameters()) {
|
||||
for (Parameter param : getInvokableParameters(invokable)) {
|
||||
Class<?> type = param.getType().getRawType();
|
||||
if (HttpRequestOptions.class.isAssignableFrom(type)
|
||||
|| HttpRequestOptions[].class.isAssignableFrom(type))
|
||||
|
@ -776,7 +770,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
|
|||
}
|
||||
|
||||
private boolean checkPresentOrNullable(Invocation invocation, String paramKey, int argIndex, Object arg) {
|
||||
if (arg == null && !invocation.getInvokable().getParameters().get(argIndex).isAnnotationPresent(Nullable.class))
|
||||
if (arg == null && !getInvokableParameters(invocation.getInvokable()).get(argIndex).isAnnotationPresent(Nullable.class))
|
||||
throw new NullPointerException(format("param{%s} for invocation %s.%s", paramKey, invocation.getInvokable()
|
||||
.getOwnerType().getRawType().getSimpleName(), invocation.getInvokable().getName()));
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue