CAMEL-11484: Optimise - Simple Language / ExpressionBuilder can use cache of frequent used expressions when having nested functions
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/52cede01 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/52cede01 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/52cede01 Branch: refs/heads/master Commit: 52cede0162ee1a2b81a70ed0ee220d1edf446bb8 Parents: b8f7e42 Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Jun 30 09:41:01 2017 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Jun 30 09:45:25 2017 +0200 ---------------------------------------------------------------------- .../apache/camel/impl/DefaultCamelContext.java | 3 ++ .../camel/language/simple/SimpleLanguage.java | 48 ++++++++++++++------ .../camel/language/LanguageServiceTest.java | 12 +++-- 3 files changed, 46 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/52cede01/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java index 4cb46f4..26a865d 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java +++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java @@ -3933,6 +3933,9 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon if (isTypeConverterStatisticsEnabled() != null) { getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled()); } + + // resolve simple language to initialize it + resolveLanguage("simple"); } /** http://git-wip-us.apache.org/repos/asf/camel/blob/52cede01/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java index ab0aa36..d62e909 100644 --- a/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java +++ b/camel-core/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java @@ -16,16 +16,17 @@ */ package org.apache.camel.language.simple; -import org.apache.camel.CamelContext; -import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.StaticService; import org.apache.camel.builder.ExpressionBuilder; import org.apache.camel.support.LanguageSupport; import org.apache.camel.util.CamelContextHelper; import org.apache.camel.util.LRUCache; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.PredicateToExpressionAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A <a href="http://camel.apache.org/simple.html">simple language</a> @@ -90,19 +91,20 @@ import org.apache.camel.util.PredicateToExpressionAdapter; * return the full path including the starting directory. * <br/> * The <b>only</b> file is the filename only with all paths clipped. - * */ -public class SimpleLanguage extends LanguageSupport { +public class SimpleLanguage extends LanguageSupport implements StaticService { + + private static final Logger LOG = LoggerFactory.getLogger(SimpleLanguage.class); // singleton for expressions without a result type private static final SimpleLanguage SIMPLE = new SimpleLanguage(); + boolean allowEscape = true; + // use caches to avoid re-parsing the same expressions over and over again private LRUCache<String, Expression> cacheExpression; private LRUCache<String, Predicate> cachePredicate; - protected boolean allowEscape = true; - /** * Default constructor. */ @@ -110,14 +112,33 @@ public class SimpleLanguage extends LanguageSupport { } @Override - public void setCamelContext(CamelContext camelContext) { - super.setCamelContext(camelContext); - + public void start() throws Exception { // setup cache which requires CamelContext to be set first - if (cacheExpression == null && cachePredicate == null && camelContext != null) { - int maxSize = CamelContextHelper.getMaximumSimpleCacheSize(camelContext); - cacheExpression = new LRUCache<>(16, maxSize, false); - cachePredicate = new LRUCache<>(16, maxSize, false); + if (cacheExpression == null && cachePredicate == null && getCamelContext() != null) { + int maxSize = CamelContextHelper.getMaximumSimpleCacheSize(getCamelContext()); + if (maxSize > 0) { + cacheExpression = new LRUCache<>(16, maxSize, false); + cachePredicate = new LRUCache<>(16, maxSize, false); + LOG.debug("Simple language predicate/expression cache size: {}", maxSize); + } else { + LOG.debug("Simple language disabled predicate/expression cache"); + } + } + } + + @Override + public void stop() throws Exception { + if (cachePredicate != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Clearing simple language predicate cache[size={}, hits={}, misses={}, evicted={}]", + cachePredicate.size(), cachePredicate.getHits(), cachePredicate.getMisses(), cachePredicate.getEvicted()); + } + } + if (cacheExpression != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Clearing simple language expression cache[size={}, hits={}, misses={}, evicted={}]", + cacheExpression.size(), cacheExpression.getHits(), cacheExpression.getMisses(), cacheExpression.getEvicted()); + } } } @@ -283,4 +304,5 @@ public class SimpleLanguage extends LanguageSupport { public void setFunctionEndToken(String endToken) { changeFunctionEndToken(endToken); } + } http://git-wip-us.apache.org/repos/asf/camel/blob/52cede01/camel-core/src/test/java/org/apache/camel/language/LanguageServiceTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/language/LanguageServiceTest.java b/camel-core/src/test/java/org/apache/camel/language/LanguageServiceTest.java index e87b775..6edfb9f 100644 --- a/camel-core/src/test/java/org/apache/camel/language/LanguageServiceTest.java +++ b/camel-core/src/test/java/org/apache/camel/language/LanguageServiceTest.java @@ -41,14 +41,16 @@ public class LanguageServiceTest extends ContextTestSupport { MyLanguage myl = (MyLanguage) context.resolveLanguage("my"); assertNotNull(myl); assertEquals("Started", myl.getState()); - assertEquals(1, context.getLanguageNames().size()); + // simple language is resolved by default hence why there is 2 + assertEquals(2, context.getLanguageNames().size()); // resolve again, should find same instance MyLanguage myl2 = (MyLanguage) context.resolveLanguage("my"); assertNotNull(myl2); assertSame(myl, myl2); assertEquals("Started", myl2.getState()); - assertEquals(1, context.getLanguageNames().size()); + // simple language is resolved by default hence why there is 2 + assertEquals(2, context.getLanguageNames().size()); context.stop(); assertEquals("Stopped", myl.getState()); @@ -58,13 +60,15 @@ public class LanguageServiceTest extends ContextTestSupport { public void testNonSingletonLanguage() throws Exception { Language tol = context.resolveLanguage("tokenize"); assertNotNull(tol); - assertEquals(1, context.getLanguageNames().size()); + // simple language is resolved by default hence why there is 2 + assertEquals(2, context.getLanguageNames().size()); // resolve again, should find another instance Language tol2 = context.resolveLanguage("tokenize"); assertNotNull(tol2); assertNotSame(tol, tol2); - assertEquals(1, context.getLanguageNames().size()); + // simple language is resolved by default hence why there is 2 + assertEquals(2, context.getLanguageNames().size()); context.stop(); assertTrue(context.getLanguageNames().isEmpty());