Hi Willem This is not a good way to cache with strong references and unlimited cache.
We need to use the LRUSoftCache from Camel itself to ensure a upper cache limit and also using weak references to the class types so we do not have classloader leaks in dynamic containers. -1 to this commit. The unit test can be reused, but we need a different way of caching. Also the cache needs to be cleaned up etc when you stop Camel etc, which the LRUSoftCache can do etc. Also using a static map for cache is not good as it causes problems when people have multiple apps in the same JVM etc. On Fri, Feb 8, 2013 at 8:27 AM, <ningji...@apache.org> wrote: > 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; > + } > +} > > -- Claus Ibsen ----------------- Red Hat, Inc. FuseSource is now part of Red Hat Email: cib...@redhat.com Web: http://fusesource.com Twitter: davsclaus Blog: http://davsclaus.com Author of Camel in Action: http://www.manning.com/ibsen