Updated Branches: refs/heads/1.6.x 962003bb0 -> 6b8ee8b90
[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. Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/6b8ee8b9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/6b8ee8b9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/6b8ee8b9 Branch: refs/heads/1.6.x Commit: 6b8ee8b904ae831b04d6f9355ee061e452408ad7 Parents: 962003b Author: Niraj Tolia <[email protected]> Authored: Tue Oct 1 00:50:17 2013 -0700 Committer: Andrew Gaul <[email protected]> Committed: Mon Oct 14 17:53:17 2013 -0700 ---------------------------------------------------------------------- .../main/java/org/jclouds/s3/util/S3Utils.java | 5 +++-- .../java/org/jclouds/reflect/Reflection2.java | 18 ++++++++++++++++++ .../org/jclouds/rest/InputParamValidator.java | 5 ++--- .../rest/internal/RestAnnotationProcessor.java | 20 +++++++------------- 4 files changed, 30 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/6b8ee8b9/apis/s3/src/main/java/org/jclouds/s3/util/S3Utils.java ---------------------------------------------------------------------- diff --git a/apis/s3/src/main/java/org/jclouds/s3/util/S3Utils.java b/apis/s3/src/main/java/org/jclouds/s3/util/S3Utils.java index 4080b22..ef836c3 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/util/S3Utils.java +++ b/apis/s3/src/main/java/org/jclouds/s3/util/S3Utils.java @@ -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); http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/6b8ee8b9/core/src/main/java/org/jclouds/reflect/Reflection2.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/reflect/Reflection2.java b/core/src/main/java/org/jclouds/reflect/Reflection2.java index 674c416..7246f64 100644 --- a/core/src/main/java/org/jclouds/reflect/Reflection2.java +++ b/core/src/main/java/org/jclouds/reflect/Reflection2.java @@ -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; http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/6b8ee8b9/core/src/main/java/org/jclouds/rest/InputParamValidator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/rest/InputParamValidator.java b/core/src/main/java/org/jclouds/rest/InputParamValidator.java index c7c5bb9..3931e39 100644 --- a/core/src/main/java/org/jclouds/rest/InputParamValidator.java +++ b/core/src/main/java/org/jclouds/rest/InputParamValidator.java @@ -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) http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/6b8ee8b9/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index 89b430c..d48d876 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -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;
