Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: Jmstemplate is a bottle neck in performance

  1. #11
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    Which is also where the difference is... When using JmsTemplate the producer is recreated each time (and if you are unlucky also the session) which takes time. Your plain solution creates a session/producer when constructed and reuse it always. So there is a difference there.

    Also you are using a single connection for both receiving and sending in the spring sample might be of influence.

    To get more information on what happens inside spring you might want to enable trace logging (this will impact performace!) for the org.springframework.jms package. That way you can see what happens.

    Another note the CachingConnectionFactory is already a single connectionFactory so you don't need to point it to another singleconnectionfactory.

    Your MessageListener isn't caching anything (but the connection) using a JmsTransactionManager will lead to caching of the consumer instead of recreation of consumers (or setting the cacheLevel property to 3 for caching/reusing the consumer) or use the cachingCOnnectionFactory instead of the singleConnectionFactory.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  2. #12
    Join Date
    Jul 2012
    Posts
    27

    Default

    thanks for the reply.
    I have a few questions:
    1. So if I understand this correctly, since i am using cachingConnectionFactory for jmsTemplate, it reuses the session/producer.
    doesn't it mean that this should increase performance since the session and producer creation each time is costly?

    2. As for reusing the connection for sending and receiving, do you mean that I should separate this and use different connections for consumer and producer? even if this is the consumer and producer which is on the same process (i have a consumer & producer per process, they don't communicate within the same process)

    3. you say that the MessageListener does not cache the consumers. but i defined concurrentConsumers=20. doesn't it mean that 20 are kept and reused?

    thanks

  3. #13
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    1. In theory it should reuse but there is a key generated to determine the reuse or not (hence my suggestion to turn on TRACE logging to see if this is actually happening)

    2. In your plain sample you also have different connections hence to create a consistent sample you should do the same for the spring one (or change the plain one to use a single connection).

    3. No... It means that there are 20 threads consuming messages it doesn't mean that it reuses MessageConsumers (in general after a poll they are closed!).

    Edit: Another difference is that Spring uses default PERSISTENT to send messages you use NON_PERSISTENT, switching that made a huge difference (at least for the plain client) when sending messages.
    Last edited by Marten Deinum; Dec 6th, 2012 at 04:41 AM.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  4. #14
    Join Date
    Jul 2012
    Posts
    27

    Default

    Thanks for the great reply.
    I tested what you suggested:
    1. separating the connections between producer and consumer increased the performance greatly (300k on 2 directions~ 600k took 45 seconds instead of about 75 seconds)
    2. updating to caching in the consumer instead of single & update the cacheLevel to 3- had no impact on performance - i tried the transaction manager but for some reason
    my computer got stuck every time i ran it and i had to restart the machine - i am not sure how this relates, maybe many connections are created.
    3. I updated the deliveryMode in jmsTemplate to be not persistence - but i didn't see any impact on performance which is weird.

    This is the new spring xml file:
    Code:
    <!-- ********************** Consumer ********************************* --> 
    	<bean id="clientListener" class="example.ClientReceive">
    		<property name="receiveQueue" ref="receiveQueue" />
    		<property name="sinkQueue" ref="sinkQueue" />
    		<property name="clientSender" ref="clientSender"/> 
    	</bean>
    
    	<bean id="containerClient"
    		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    		<property name="concurrentConsumers" value="20"/><!-- if it is not 1 - it is difficult to see distribution to other services!!!change to 50,20 -->
                <property name="maxConcurrentConsumers" value="50"/><!-- if it is not 1 - it is difficult to see distribution to other services!!!change to 50-->
                <property name="idleTaskExecutionLimit" value="10"/>
    		 <property name="connectionFactory" ref="cachingConnectionFactoryConsumer" />
    		<property name="destination" ref="receiveQueue" />
    		<property name="messageListener" ref="clientListener" />
    		<property name="cacheLevel" value="3"/> <!-- CACHE_CONSUMER: cache a shared JMS Connection, a JMS Session, and a JMS MessageConsumer for each listener thread. -->
    		<property name="sessionAcknowledgeMode" value="1"/>
    	</bean>
    	
    	<bean id="receiveQueue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg value="queueA"/>
        </bean>
        <bean id="sinkQueue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg value="sinkQueue"/>
        </bean>
        
        <bean id="connectionFactoryConsumer" 
    		class="org.apache.activemq.ActiveMQConnectionFactory">
    		 <property name="brokerURL" value="failover:(tcp://localhost:61616)?randomize=false" />    <!-- Single broker-->
    	</bean>
    	
        <bean id="singleConnectionFactoryConsumer" class="org.springframework.jms.connection.SingleConnectionFactory">
        	 <property name="targetConnectionFactory"
        		ref="connectionFactoryConsumer" />
        		<property name="reconnectOnException" value="true"/>
        </bean>
        
         <bean id="cachingConnectionFactoryConsumer"  
    		class="org.springframework.jms.connection.CachingConnectionFactory">
    		<!-- <constructor-arg ref="singleConnectionFactoryConsumer"/> -->
    		<constructor-arg ref="connectionFactoryConsumer"/>
    		<property name="sessionCacheSize" value="100" /> 
    	</bean>  
    	<!--<bean id="jmsTransactionManagerConsumer" class="org.springframework.jms.connection.JmsTransactionManager">
    		<property name="connectionFactory" ref="connectionFactoryConsumer" />
    	</bean>-->
        <!-- **********************  END-Consumer *****************************	-->
        
    	
    	<!-- ********************** Producer ********************************* --> 
    	<bean id="clientSender" class="example.ClientSend">
    		 <property name="sendQueue" ref="sendQueue" /> 
    		 <property name="jmsTemplate" ref="jmsTemplate"/>  
    	</bean>
    	
    	 <bean id="sendQueue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg value="queueB"/>
        </bean> 
        
         <!-- for send response on temp q-->
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
             <property name="connectionFactory" ref="cachingConnectionFactoryProducer"/>
             <property name="deliveryMode" value="1"/>  
         </bean>
    	
    	  <bean id="connectionFactoryProducer" 
    		class="org.apache.activemq.ActiveMQConnectionFactory">
    		 <property name="brokerURL" value="failover:(tcp://localhost:61616)?randomize=false" />    <!-- Single broker-->
    	</bean>
    	
    	<bean id="cachingConnectionFactoryProducer"  
    		class="org.springframework.jms.connection.CachingConnectionFactory">
    		<constructor-arg ref="connectionFactoryProducer"/>
    		<property name="sessionCacheSize" value="100" /> 
    	</bean>   
    	
    	<!-- ********************** END Producer ********************************* -->

  5. #15
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    Did more or less the same.

    Sending 5K messages with a plain producer takes ~1 second less as compared with jmsTemplate. This is without connection sharing between the listener container and template. When I enable that jmsTemplate takes 3 times as long as a plain version but that is probably due to the multithreading and contention for the pool/caching mechanism.

    When using the cachingConnectionFactory you don't need to additionally set the cache level, caching is now handled by the connectionfactory and its related classes so this doesn't impact performance (at least not noticably I suspect).

    Also tried playing around with (NON)Persistent but that appears to be changing nothing for the JmsTemplate it has a great impact ont he plain client when setting it to Persistent.

    Edit: Next to setting the delivery mode you also need to enable explicitQosEnabled on the JmsTemplate (forgot about that ).
    Last edited by Marten Deinum; Dec 6th, 2012 at 05:43 AM.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  6. #16
    Join Date
    Jul 2012
    Posts
    27

    Default

    After adding the explicitQosEnabled - i see an improvement. so now it takes about 33 seconds instead of 75 seconds.
    This is great news.
    thanks a lot.

  7. #17
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    If you change the plain client to use the same send method as JmsTemplate does send(message, deliverymode, priority, ttl) you will see that the performance difference is even smaller.

    Jmstemplate has a (small) overhead as it does some delegation and checking which you don't have to do when doing all the stuff manually. This is the price to pay for using a more abstract solution. IMHO it is worth it but that is for each to decide.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •