This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch opt-exchangekey in repository https://gitbox.apache.org/repos/asf/camel.git
commit 73d3b17d1805202672af4c692774204d0e575c77 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Mar 12 06:50:05 2021 +0100 CAMEL-16326: camel-core - Optimize usage of exchanage properties for state in routing engine. --- .../src/main/java/org/apache/camel/Exchange.java | 13 +++++++++++-- .../java/org/apache/camel/ExchangePropertyKey.java | 6 ------ .../main/java/org/apache/camel/ExtendedExchange.java | 1 + .../camel/impl/engine/CamelInternalProcessor.java | 7 ++++++- .../org/apache/camel/impl/DefaultExchangeTest.java | 15 ++++++++++++++- .../org/apache/camel/support/AbstractExchange.java | 20 ++++++++++++++++++-- .../apache/camel/support/DefaultPooledExchange.java | 3 ++- 7 files changed, 52 insertions(+), 13 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java b/core/camel-api/src/main/java/org/apache/camel/Exchange.java index 1111043..f565313 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java +++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java @@ -404,13 +404,22 @@ public interface Exchange { boolean removeProperties(String pattern, String... excludePatterns); /** - * Returns all of the properties associated with the exchange + * Returns the properties associated with the exchange * - * @return all the properties in a Map + * @return the properties in a Map + * @see #getAllProperties() */ Map<String, Object> getProperties(); /** + * Returns all (both internal and custom) of the properties associated with the exchange + * + * @return all (both internal and custom) the properties in a Map + * @see #getProperties() + */ + Map<String, Object> getAllProperties(); + + /** * Returns whether any properties has been set * * @return <tt>true</tt> if any properties has been set diff --git a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java index c4d2c68..0f5978e 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java @@ -21,12 +21,6 @@ package org.apache.camel; */ public enum ExchangePropertyKey { - // TODO: sort by most commonly used (not A..Z) - // so we can say 0..10 are frequently used - // and 11..end are possible used - // then we can optimize and have dirty flags for possible used - // and if not dirty then no need to go so far in the array - AGGREGATED_COMPLETED_BY(Exchange.AGGREGATED_COMPLETED_BY), AGGREGATED_CORRELATION_KEY(Exchange.AGGREGATED_CORRELATION_KEY), AGGREGATED_SIZE(Exchange.AGGREGATED_SIZE), diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java index bf1866e..d51da72 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedExchange.java @@ -182,6 +182,7 @@ public interface ExtendedExchange extends Exchange { /** * Gets the internal properties from this exchange. + * The known set of internal keys is defined in {@link ExchangePropertyKey}. * <p/> * This method is only intended for Camel internally. * diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java index 981110f..289b289 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java @@ -107,6 +107,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In private final ShutdownStrategy shutdownStrategy; private final List<CamelInternalProcessorAdvice<?>> advices = new ArrayList<>(); private byte statefulAdvices; + private Object[] EMPTY_STATEFUL_STATES; private PooledObjectFactory<CamelInternalTask> taskFactory; public CamelInternalProcessor(CamelContext camelContext) { @@ -132,6 +133,9 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In int capacity = camelContext.adapt(ExtendedCamelContext.class).getExchangeFactory().getCapacity(); taskFactory.setCapacity(capacity); LOG.trace("Using TaskFactory: {}", taskFactory); + + // create empty array we can use for reset + EMPTY_STATEFUL_STATES = new Object[statefulAdvices]; } ServiceHelper.buildService(taskFactory, processor); @@ -223,7 +227,8 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In @Override public void reset() { - Arrays.fill(states, null); + // reset array by copying over from empty which is a very fast JVM optimized operation + System.arraycopy(EMPTY_STATEFUL_STATES, 0, states, 0, statefulAdvices); this.exchange = null; this.originalCallback = null; } diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeTest.java index 19a8c2f..8e77d35 100644 --- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeTest.java @@ -23,6 +23,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.ExchangePropertyKey; import org.apache.camel.ExchangeTestSupport; +import org.apache.camel.ExtendedExchange; import org.apache.camel.InvalidPayloadException; import org.apache.camel.Message; import org.apache.camel.RuntimeCamelException; @@ -231,7 +232,7 @@ public class DefaultExchangeTest extends ExchangeTestSupport { } @Test - public void testRemoveKnownProperties() throws Exception { + public void testRemoveInternalProperties() throws Exception { exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, "iso-8859-1"); assertEquals("iso-8859-1", exchange.getProperty(ExchangePropertyKey.CHARSET_NAME)); @@ -255,6 +256,18 @@ public class DefaultExchangeTest extends ExchangeTestSupport { } @Test + public void testAllProperties() throws Exception { + exchange.removeProperties("*"); + exchange.setProperty("foo", 123); + exchange.setProperty(ExchangePropertyKey.TO_ENDPOINT, "seda:bar"); + exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, "iso-8859-1"); + + assertEquals(1, exchange.getProperties().size()); + assertEquals(2, exchange.adapt(ExtendedExchange.class).getInternalProperties().size()); + assertEquals(3, exchange.getAllProperties().size()); + } + + @Test public void testInType() throws Exception { exchange.setIn(new MyMessage(context)); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java index bb24ecd..62e4f1f 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java @@ -52,11 +52,16 @@ import org.apache.camel.util.ObjectHelper; */ class AbstractExchange implements ExtendedExchange { + // number of elements in array + static final int INTERNAL_LENGTH = ExchangePropertyKey.values().length; + // empty array for reset + static final Object[] EMPTY_INTERNAL_PROPERTIES = new Object[INTERNAL_LENGTH]; + final CamelContext context; // optimize to create properties always and with a reasonable small size final Map<String, Object> properties = new ConcurrentHashMap<>(8); // optimize for internal exchange properties (not intended for end users) - final Object[] internalProperties = new Object[ExchangePropertyKey.values().length]; + final Object[] internalProperties = new Object[INTERNAL_LENGTH]; long created; Message in; Message out; @@ -358,7 +363,8 @@ class AbstractExchange implements ExtendedExchange { // special optimized if (excludePatterns == null && "*".equals(pattern)) { properties.clear(); - Arrays.fill(internalProperties, null); + // reset array by copying over from empty which is a very fast JVM optimized operation + System.arraycopy(EMPTY_INTERNAL_PROPERTIES, 0, this.internalProperties, 0, INTERNAL_LENGTH); return true; } @@ -409,6 +415,16 @@ class AbstractExchange implements ExtendedExchange { } @Override + public Map<String, Object> getAllProperties() { + // include also internal properties (creates a new map) + Map<String, Object> map = getInternalProperties(); + if (!properties.isEmpty()) { + map.putAll(properties); + } + return map; + } + + @Override public boolean hasProperties() { return !properties.isEmpty(); } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java index f3bad21..11b6bd4 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java @@ -78,7 +78,8 @@ public final class DefaultPooledExchange extends AbstractExchange implements Poo if (created > 0 && (forced || autoRelease)) { this.created = 0; // by setting to 0 we also flag that this exchange is done and needs to be reset to use again this.properties.clear(); - Arrays.fill(this.internalProperties, null); + // reset array by copying over from empty which is a very fast JVM optimized operation + System.arraycopy(EMPTY_INTERNAL_PROPERTIES, 0, this.internalProperties, 0, INTERNAL_LENGTH); this.exchangeId = null; if (in != null && in.getClass() == originalInClassType) { // okay we can reuse in