Since Camel 3.9
Apache Camel requires a tiny resource overhead when routing message.
For example the routing engine keeps state of each individual message, keeping track of the message flow, and where messaging are going next. The routing engine also handles complex tasks such as error handling, capturing metrics, and many other things. All together small numbers of Java objects is allocated on the heap for each processing step during routing.
With the advance of cloud computing, where work loads are precisely measured, then Camel has undergone a series of core optimizations to reduce its overhead.
The Exchange Pooling functionality is object pooling by recycling commonly used objects by the routing enginge.
The most significant object being reused is the
org.apache.camel.Exchange object that is the root object that holds the message with its payload, headers, meta-data and other content.
Besides pooling exchanges then internal objects used by the routing engine is also pooled and recycled. All together this dramatically reduces the object allocations, from camel core itself.
There will always be objects allocations from the actual message content (payload and headers), and also from the Camel components in use and its 3rd party libraries. The footprint of Camel core and its routing engine is close to zero, when pooling is enabled.
This all sounds marvelous so what is the negatives? Yes the price to pay for object pooling, is the complexity of managing the pool (acquire and returning objects to the pool); however all of this is taken care of by Camel itself. The object pools are using JDK
ConcurrentMap instances and take up very little memory. The negative is very tiny CPU cost on adding and removing objects from the pools, and resetting the objects before reuse.
It is possible better to sacrifice the very tiny CPU cost for reduced object allocations, which helps to avoid the JVM garbage collection running more frequently, and causing your application to halt or delay processing messages at any given time.
The object pooling is currently not enabled by default, and requires to be turned on.
This can be done as shown in Java:
CamelContext context = ... context.adapt(ExtendedCamelContext.class).setExchangeFactory(new PooledExchangeFactory());
If using Camel Main, Camel Spring Boot, or Camel Quarkus you can enable this in the
camel.main.exchange-factory = pooled
The exchange pool can be configured with the following options:
Whether to use pooling or not. Possible values are prototype or pooled
Maximum number of elemenets in the pool
Whether to capture usage statistics
If object pooling is enabled, then Camel provides a JMX MBean which allows to introspect the pools and its usage via JMX. This requires to add
camel-management JAR to the classpath.
We have provided a few examples which we are using for performance profiling. For example the basic
timer-log example is on github at: https://github.com/apache/camel-performance-tests/tree/master/profiling/timer-log