You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2016/07/21 10:01:34 UTC

[4/5] camel git commit: CAMEL-10106: [api-component-framework] Reduce object allocation in ApiMethodHelper, ApiMethodImpl

CAMEL-10106: [api-component-framework] Reduce object allocation in ApiMethodHelper, ApiMethodImpl


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/aac2662a
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/aac2662a
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/aac2662a

Branch: refs/heads/master
Commit: aac2662ab66b65c65e8d723d68a02678ecc0727c
Parents: 90ac673
Author: lburgazzoli <lb...@gmail.com>
Authored: Thu Jun 30 14:10:13 2016 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Thu Jul 21 11:47:40 2016 +0200

----------------------------------------------------------------------
 .../camel/util/component/ApiMethodHelper.java   | 84 +++++++++++++-------
 .../camel/util/component/ApiMethodImpl.java     | 17 ++--
 2 files changed, 65 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/aac2662a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
index 3d06e3f..8d09517 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
@@ -28,7 +28,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
 import org.apache.camel.RuntimeCamelException;
 import org.slf4j.Logger;
@@ -42,16 +41,18 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
     private static final Logger LOG = LoggerFactory.getLogger(ApiMethodHelper.class);
 
     // maps method name to ApiMethod
-    private final Map<String, List<T>> methodMap = new HashMap<String, List<T>>();
+    private final Map<String, List<T>> methodMap;
 
     // maps method name to method arguments of the form Class type1, String name1, Class type2, String name2,...
-    private final Map<String, List<Object>> argumentsMap = new HashMap<String, List<Object>>();
+    private final Map<String, List<Object>> argumentsMap;
 
     // maps argument name to argument type
-    private final Map<String, Class<?>> validArguments = new HashMap<String, Class<?>>();
+    private final Map<String, Class<?>> validArguments;
 
     // maps aliases to actual method names
-    private final HashMap<String, Set<String>> aliasesMap = new HashMap<String, Set<String>>();
+    private final Map<String, Set<String>> aliasesMap;
+
+    // nullable args
     private final List<String> nullableArguments;
 
     /**
@@ -62,6 +63,11 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      */
     public ApiMethodHelper(Class<T> apiMethodEnum, Map<String, String> aliases, List<String> nullableArguments) {
 
+        Map<String, List<T>> tmpMethodMap = new HashMap<>();
+        Map<String, List<Object>> tmpArgumentsMap = new HashMap<>();
+        Map<String, Class<?>> tmpValidArguments = new HashMap<>();
+        Map<String, Set<String>> tmpAliasesMap = new HashMap<>();
+
         // validate ApiMethod Enum
         if (apiMethodEnum == null) {
             throw new IllegalArgumentException("ApiMethod enumeration cannot be null");
@@ -103,28 +109,28 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                         builder.append(Character.toLowerCase(firstChar)).append(alias.substring(1));
                         alias = builder.toString();
                     }
-                    Set<String> names = aliasesMap.get(alias);
+                    Set<String> names = tmpAliasesMap.get(alias);
                     if (names == null) {
                         names = new HashSet<String>();
-                        aliasesMap.put(alias, names);
+                        tmpAliasesMap.put(alias, names);
                     }
                     names.add(name);
                 }
             }
 
             // map method name to Enum
-            List<T> overloads = methodMap.get(name);
+            List<T> overloads = tmpMethodMap.get(name);
             if (overloads == null) {
                 overloads = new ArrayList<T>();
-                methodMap.put(method.getName(), overloads);
+                tmpMethodMap.put(method.getName(), overloads);
             }
             overloads.add(method);
 
             // add arguments for this method
-            List<Object> arguments = argumentsMap.get(name);
+            List<Object> arguments = tmpArgumentsMap.get(name);
             if (arguments == null) {
                 arguments = new ArrayList<Object>();
-                argumentsMap.put(name, arguments);
+                tmpArgumentsMap.put(name, arguments);
             }
 
             // process all arguments for this method
@@ -140,27 +146,27 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                 }
 
                 // also collect argument names for all methods, and detect clashes here
-                final Class<?> previousType = validArguments.get(argName);
+                final Class<?> previousType = tmpValidArguments.get(argName);
                 if (previousType != null && previousType != argType) {
                     throw new IllegalArgumentException(String.format(
                         "Argument %s has ambiguous types (%s, %s) across methods!",
                         name, previousType, argType));
                 } else if (previousType == null) {
-                    validArguments.put(argName, argType);
+                    tmpValidArguments.put(argName, argType);
                 }
             }
 
         }
 
         // validate nullableArguments
-        if (!validArguments.keySet().containsAll(this.nullableArguments)) {
+        if (!tmpValidArguments.keySet().containsAll(this.nullableArguments)) {
             List<String> unknowns = new ArrayList<String>(this.nullableArguments);
-            unknowns.removeAll(validArguments.keySet());
+            unknowns.removeAll(tmpValidArguments.keySet());
             throw new IllegalArgumentException("Unknown nullable arguments " + unknowns.toString());
         }
 
         // validate aliases
-        for (Map.Entry<String, Set<String>> entry : aliasesMap.entrySet()) {
+        for (Map.Entry<String, Set<String>> entry : tmpAliasesMap.entrySet()) {
 
             // look for aliases that match multiple methods
             final Set<String> methodNames = entry.getValue();
@@ -169,7 +175,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                 // get mapped methods
                 final List<T> aliasedMethods = new ArrayList<T>();
                 for (String methodName : methodNames) {
-                    List<T> mappedMethods = methodMap.get(methodName);
+                    List<T> mappedMethods = tmpMethodMap.get(methodName);
                     aliasedMethods.addAll(mappedMethods);
                 }
 
@@ -199,7 +205,12 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
             }
         }
 
-        LOG.debug("Found {} unique method names in {} methods", methodMap.size(), methods.length);
+        this.methodMap = Collections.unmodifiableMap(tmpMethodMap);
+        this.argumentsMap = Collections.unmodifiableMap(tmpArgumentsMap);
+        this.validArguments = Collections.unmodifiableMap(tmpValidArguments);
+        this.aliasesMap = Collections.unmodifiableMap(tmpAliasesMap);
+
+        LOG.debug("Found {} unique method names in {} methods", tmpMethodMap.size(), methods.length);
     }
 
     /**
@@ -225,10 +236,10 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
         List<T> methods = methodMap.get(name);
         if (methods == null) {
             if (aliasesMap.containsKey(name)) {
-                methods = aliasesMap.get(name)
-                    .stream()
-                    .map(method -> (T)methodMap.get(method))
-                    .collect(Collectors.toList());
+                methods = new ArrayList<T>();
+                for (String method : aliasesMap.get(name)) {
+                    methods.addAll(methodMap.get(method));
+                }
             }
         }
         if (methods == null) {
@@ -282,9 +293,9 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
         }
 
         // list of methods that have all args in the given names
-        final List<ApiMethod> result = new ArrayList<ApiMethod>();
-        final List<ApiMethod> extraArgs = new ArrayList<ApiMethod>();
-        final List<ApiMethod> nullArgs = new ArrayList<ApiMethod>();
+        List<ApiMethod> result = new ArrayList<>();
+        List<ApiMethod> extraArgs = null;
+        List<ApiMethod> nullArgs = null;
 
         for (ApiMethod method : methods) {
             final List<String> methodArgs = method.getArgNames();
@@ -308,13 +319,20 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                     if (methodArgs.containsAll(argNames)) {
                         // prefer exact match to avoid unused args
                         result.add(method);
-                    } else {
+                    } else if (result.isEmpty()) {
+                        // if result is empty, add method to extra args list
+                        if (extraArgs == null) {
+                            extraArgs = new ArrayList<>();
+                        }
                         // method takes a subset, unused args
                         extraArgs.add(method);
                     }
-                } else if (result.isEmpty() && extraArgs.isEmpty()) {
+                } else if (result.isEmpty() && extraArgs != null && extraArgs.isEmpty()) {
                     // avoid looking for nullable args by checking for empty result and extraArgs
                     if (withNullableArgsList != null && withNullableArgsList.containsAll(methodArgs)) {
+                        if (nullArgs == null) {
+                            nullArgs = new ArrayList<>();
+                        }
                         nullArgs.add(method);
                     }
                 }
@@ -322,8 +340,14 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
             }
         }
 
+        List<ApiMethod> methodList = result.isEmpty()
+            ? (extraArgs != null && extraArgs.isEmpty())
+                ? nullArgs
+                : extraArgs
+            : result;
+
         // preference order is exact match, matches with extra args, matches with null args
-        return Collections.unmodifiableList(result.isEmpty() ? (extraArgs.isEmpty() ? nullArgs : extraArgs) : result);
+        return methodList != null ? Collections.unmodifiableList(methodList) : Collections.emptyList();
     }
 
     /**
@@ -372,7 +396,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return alias names mapped to method names.
      */
     public Map<String, Set<String>> getAliases() {
-        return Collections.unmodifiableMap(aliasesMap);
+        return aliasesMap;
     }
 
     /**
@@ -380,7 +404,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return map with argument names as keys, and types as values
      */
     public Map<String, Class<?>> allArguments() {
-        return Collections.unmodifiableMap(validArguments);
+        return validArguments;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/aac2662a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
index 75c66a6..324ac80 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
@@ -65,14 +65,18 @@ public final class ApiMethodImpl implements ApiMethod {
             throw new IllegalArgumentException("Invalid parameter list, "
                 + "must be of the form 'Class arg1, String arg1Name, Class arg2, String arg2Name...");
         }
+
         int nArgs = args.length / 2;
-        this.argNames = new ArrayList<String>(nArgs);
-        this.argTypes = new ArrayList<Class<?>>(nArgs);
+        final List<String> tmpArgNames = new ArrayList<>(nArgs);
+        final List<Class<?>> tmpArgTypes = new ArrayList<>(nArgs);
         for (int i = 0; i < nArgs; i++) {
-            this.argTypes.add((Class<?>) args[i * 2]);
-            this.argNames.add((String) args[i * 2 + 1]);
+            tmpArgTypes.add((Class<?>) args[i * 2]);
+            tmpArgNames.add((String) args[i * 2 + 1]);
         }
 
+        this.argNames = Collections.unmodifiableList(tmpArgNames);
+        this.argTypes = Collections.unmodifiableList(tmpArgTypes);
+
         // find method in Proxy type
         try {
             this.method = proxyType.getMethod(name, argTypes.toArray(new Class[nArgs]));
@@ -95,12 +99,12 @@ public final class ApiMethodImpl implements ApiMethod {
 
     @Override
     public List<String> getArgNames() {
-        return Collections.unmodifiableList(argNames);
+        return argNames;
     }
 
     @Override
     public List<Class<?>> getArgTypes() {
-        return Collections.unmodifiableList(argTypes);
+        return argTypes;
     }
 
     @Override
@@ -117,6 +121,7 @@ public final class ApiMethodImpl implements ApiMethod {
             .append(", argNames=").append(argNames)
             .append(", argTypes=").append(argTypes)
             .append("}");
+
         return builder.toString();
     }
 }