Author: ningjiang Date: Fri Feb 8 07:27:11 2013 New Revision: 1443858 URL: http://svn.apache.org/r1443858 Log: CAMEL-6043 Added a cache for the BeanInfo
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTestRunner.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java?rev=1443858&r1=1443857&r2=1443858&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Fri Feb 8 07:27:11 2013 @@ -55,10 +55,9 @@ import org.slf4j.LoggerFactory; /** * Represents the metadata about a bean type created via a combination of * introspection and annotations together with some useful sensible defaults - * - * @version */ public class BeanInfo { + public static final String BEAN_INFO_CACHE_REGISTRY_KEY = "CamelBeanInfoCache"; private static final transient Logger LOG = LoggerFactory.getLogger(BeanInfo.class); private static final String CGLIB_CLASS_SEPARATOR = "$$"; private static final List<Method> EXCLUDED_METHODS = new ArrayList<Method>(); @@ -105,6 +104,21 @@ public class BeanInfo { this.type = type; this.strategy = strategy; + Map<CacheKey, BeanInfo> cache = (Map<CacheKey, BeanInfo>) camelContext.getRegistry().lookupByNameAndType(BEAN_INFO_CACHE_REGISTRY_KEY, Map.class); + CacheKey cacheKey = new CacheKey(type, explicitMethod, strategy); + if (cache != null) { + BeanInfo beanInfo = cache.get(cacheKey); + if (beanInfo != null) { + defaultMethod = beanInfo.defaultMethod; + operations = beanInfo.operations; + operationsWithBody = beanInfo.operationsWithBody; + operationsWithNoBody = beanInfo.operationsWithNoBody; + operationsWithCustomAnnotation = beanInfo.operationsWithCustomAnnotation; + operationsWithHandlerAnnotation = beanInfo.operationsWithHandlerAnnotation; + methodMap = beanInfo.methodMap; + return; + } + } if (explicitMethod != null) { // must be a valid method if (!isValidMethod(type, explicitMethod)) { @@ -133,6 +147,10 @@ public class BeanInfo { operationsWithCustomAnnotation = Collections.unmodifiableList(operationsWithCustomAnnotation); operationsWithHandlerAnnotation = Collections.unmodifiableList(operationsWithHandlerAnnotation); methodMap = Collections.unmodifiableMap(methodMap); + + if (cache != null) { + cache.put(cacheKey, this); + } } public Class<?> getType() { @@ -1007,5 +1025,49 @@ public class BeanInfo { return null; } + + private static final class CacheKey { + private final Class<?> type; + private final Method explicitMethod; + private final Class<? extends ParameterMappingStrategy> strategyClass; + + public CacheKey(Class<?> type, Method explicitMethod, ParameterMappingStrategy strategy) { + this.type = type; + this.explicitMethod = explicitMethod; + this.strategyClass = strategy.getClass(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CacheKey cacheKey = (CacheKey) o; + + if (explicitMethod != null ? !explicitMethod.equals(cacheKey.explicitMethod) : cacheKey.explicitMethod != null) { + return false; + } + if (!strategyClass.equals(cacheKey.strategyClass)) { + return false; + } + if (!type.equals(cacheKey.type)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + (explicitMethod != null ? explicitMethod.hashCode() : 0); + result = 31 * result + strategyClass.hashCode(); + return result; + } + } } Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTestRunner.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTestRunner.java?rev=1443858&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTestRunner.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/CamelSimpleExpressionPerfTestRunner.java Fri Feb 8 07:27:11 2013 @@ -0,0 +1,80 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.bean; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.SimpleRegistry; +import org.apache.camel.spi.Registry; + +public final class CamelSimpleExpressionPerfTestRunner { + private static final int MESSAGE_LOOP_COUNT = 10000; + private static final int TEST_EXECUTION_COUNT = 5; + + private CamelSimpleExpressionPerfTestRunner() { + //Utils class + } + + public static void main(String[] args) throws Exception { + long bodyOnly = executePerformanceTest(new SimpleRegistry(), "${body}"); + long bodyProperty = executePerformanceTest(new SimpleRegistry(), "${body[p]}"); + + SimpleRegistry registry = new SimpleRegistry(); + registry.put(BeanInfo.BEAN_INFO_CACHE_REGISTRY_KEY, new HashMap()); + long bodyPropertyWithCache = executePerformanceTest(registry, "${body[p]}"); + + System.out.printf("${body}: %dms%n", bodyOnly); + System.out.printf("${body[p]} : %dms%n", bodyProperty); + System.out.printf("${body[p]} with cache : %dms%n", bodyPropertyWithCache); + } + + private static long executePerformanceTest(Registry registry, final String simpleExpression) throws Exception { + CamelContext ctx = new DefaultCamelContext(registry); + + ctx.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start").loop(MESSAGE_LOOP_COUNT).setHeader("test").simple(simpleExpression).to("mock:plop"); + } + }); + + ctx.start(); + + Map<String, String> body = new HashMap<String, String>(); + body.put("p", "q"); + + ProducerTemplate template = ctx.createProducerTemplate(); + // Initial one, it's a dry start, we don't care about this one. + template.sendBody("direct:start", body); + + // Measure the duration of the executions in nanoseconds + long totalNsDuration = 0; + for (int i = 0; i < TEST_EXECUTION_COUNT; i++) { + long tick = System.nanoTime(); + template.sendBody("direct:start", body); + totalNsDuration += System.nanoTime() - tick; + } + + // Return the average duration in milliseconds + return totalNsDuration / TEST_EXECUTION_COUNT / 1000 / 1000; + } +}