1 2 Previous Next 29 Replies Latest reply on Jun 17, 2013 9:57 AM by Clebert Suconic

    HornetQ is 15 times slower than JBossMQ !

    petal1 Newbie

      Hello,

       

      I am in the process of migrating from JBoss 4.0.4 to JBoss 6.1. The main driver for this is that we feel JBossMQ in JBoss 4.0.4 is a bottleneck in our application.

       

      To get a feel for how much faster HornetQ is that JBossMQ, I wrote a simple little test harness.

       

      The JBoss4.0.4 and JBoss6.1 installations for this test had nothing deployed except the queue definition.

       

      I then wrote two very simple standalone java programs - one acting as a MessageListener that prints the contents of the TextMessages it receives, and the other looping round sending TextMessages to the queue for a defined duration of 5 seconds.

       

      The listener on the HornetQ system receives this many messages (3 runs):

      30

      115

      128

       

      and the JBossMQ system receives this many messages (3 runs):

      1873

      1953

      1785

       

      So HornetQ is at least 15 times slower than JBossMQ. I have tried to offer a level playing field, but if anyone can think of a reason for the awful performance of HornetQ compared with JBossMQ then I'd be grateful to hear it.

       

      Thanks,

      Paul

        • 1. Re: HornetQ is 15 times slower than JBossMQ !
          Yong Hao Gao Master

          Can you give us more of the details of your test configuration?

           

          Thanks

          Howard

          • 2. Re: HornetQ is 15 times slower than JBossMQ !
            Clebert Suconic Master

            +1 on Howard:

             

            Without context there isn't much we can say...

             

            For example: When you send a persistent message, you have to guarantee it was persisted before you delivered it. So, a single producer will be bound by your hardware capacity on syncs. I believe JBoss MQ wasn't respecting some of these semantics... That doesn't mean that's the overal performance...

             

            128 sounds about right on what a disk can perform. You can configure the system to not block on sends and that would be much faster.. but that depends on what you need for your system.

             

            But again: without more context.. there isn't much we can say.

            • 3. Re: HornetQ is 15 times slower than JBossMQ !
              petal1 Newbie

              Thank you both for taking the time to reply.

               

              You asked what I am trying to achieve - well, at this stage I want to maximise the throughput of messages being sent and processed by the JMS provider to give a basic indication on the difference in speed between JBossMQ and HornetQ.

               

              We use JMS queues and topics extensively throughout our application, and we will have different requirements for different queues/topics etc,  but what I wanted to get from my test was a simple comparison between the speed of JBossMQ and HornetQ.

               

              To do that I installed JBoss 4.0.4 on one linux box and JBoss 6.1.0 on an identical box (actually Amazon EC2 instances). I did no configuration to either installation apart from drop a queue definition into deploy/jms on the 4.0.4 box and the equivalent into deploy/hornetq on the 6.1.0 box. Well, I did add this to hornetq-configuration.xml:

                        <security-enabled>false</security-enabled>

              but that was all I changed.

               

              I then ran two Java applications on each machine. One to send to the queue and one to receive from it. The listener on the hornetq box terminated immediately but Clebert told me the reason for that - JBossMQ provides a thread for the consumer but HornetQ doesn't, so I need to keep the program alive in the HornetQ case. So I added an infinite while/true loop in my listener; that kept the listener alive and it did process messages (in the onMessage method) sent to the queue by the sender program. But only 150 messages were processed in the timeframe. That is compared to the 3500 (numbers from my latest test) messages being processed by onMessage in the JBossMQ scenario.

               

              I am not sure if I am being fair in that my HornetQ test has the infinite while/true loop in the main method that the JBossMQ one does not need?

               

              With that doubt in mind, I set up another test - no MessageListeners for either JBossMQ or HornetQ this time; instead just an infinite loop that calls MessageConsumer.receive(0):

                  while (true)

                  {

                      Message m = m_consumer.receive(0);

                      if (m != null)

                      {

                          message = (TextMessage) m;

                          System.out.println("Received message: " + message.getText());

                      }

                  }

               

              The messages processed in this test were:

               

                   JBossMQ:

                        4069

                        4431

                        4378

               

                   HornetQ:

                        3130

                        3528

                        3547

               

              So even then HornetQ is considerably slower.

               

              Perhaps the out of the box configuration for JBossMQ is more suited to this test than HornetQ, but so far I'm very disappointed that HornetQ is performing so poorly against the much maligned and old implementation that JBossMQ is.

               

              Thanks,

              Paul

              • 4. Re: HornetQ is 15 times slower than JBossMQ !
                Clebert Suconic Master

                I didn't ask what you're trying to achieve, you are diverging from the question.. I asked what you are doing.. and I have no idea on how you are producing, if you are persistent, if you're not.... if you are doing a single producer...

                 

                JBoss MQ doesn't guarantee you syncs on delivery. You can't outperform your IO capability on a single producer or a single consumer unless you don't respect syncs. When you add multipl producers and multiple consumers a good message system should be able to batch multiple threads and make a single write / sync request for simuntaneous requests.

                 

                 

                You can't just do a blind comparisson like that without understanding the real implication.. that's a really bad practice..  I will not be able to help you until you provide us something more measurable.

                 

                On a bad benchmark like you're doing you could have a false impression on JBoss MQ being more performant but in reality you're just not syncing anything.

                 

                 

                If you just want to make the numbers higher, set blockOnPersistentSend=false, and block on acknowledge=false (if you are not using transactions) at the connection factory and the number will be much higher. But a warning: that's only valid for dumb benchmarks.. which we care more about real systems.

                 

                You need to measure real scenarios if you want more realistic numbers...

                 

                 

                I would be happy to assist you to improve your benchmarks.. but so far the only information I have is your numbers are higher on JBoss MQ.. which tells me absolutely nothing!

                • 5. Re: HornetQ is 15 times slower than JBossMQ !
                  Clebert Suconic Master

                  BTW: blockOnPersistentSend=false and blockOnAck=false may be suitable for your system if you can afford eventual message loss on eventual crashes of your client... that's not a decision I can make.

                  • 6. Re: HornetQ is 15 times slower than JBossMQ !
                    petal1 Newbie

                    I am sorry if I answered what I was trying to achieve rather than what I was doing. What I am doing is taking the out of the box configuration of the JMS Provider on JBoss 4.0.4 and JBoss 6.1.0 and exectuing extremely basic Java programs to send and receive messages and seeing what the perfomance is like in both environments. I hope that's clear enough.


                    I hear what you're saying about a false comparison. But out of the box, without configuring either JBossMQ or HornetQ, and running a JMS test program from page 1 of any JMS book, HornetQ is considerably slower than JBossMQ.

                     

                    You say that the only information you have is that the numbers are higher on JBossMQ. Well, I have told you that the configuration of each system is the one that comes with an unadulterated install of the particular JBoss versions. So that tells you the configuration of each environment.

                     

                    You also say that is a "bad benchmark". Maybe. But to do a good benchmark I would need to configure the systems to provide the same functionality, and that would mean knowing what every setting and its value should be to achieve that. Life's too short. But I will start with the two you mention and see if that does indeed increase the throughput (even if that will give a "dumb" benchmark).

                    • 7. Re: HornetQ is 15 times slower than JBossMQ !
                      Justin Bertram Master

                      Can you attach both the producing and consuming Java applications you are using for this test? 

                       

                      Also, can you elaborate on how you are executing the applications?  For example, are you are running multiple instances of each or just one?

                       

                      I understand what you're saying about life being too short, but that sentiment cuts both ways.  Life is also too short to waste on bad benchmark comparisons.  Anything worth doing is worth doing right.

                      • 8. Re: HornetQ is 15 times slower than JBossMQ !
                        Clebert Suconic Master

                        am sorry if I answered what I was trying to achieve rather than what I was doing. What I am doing is taking the out of the box configuration of the JMS Provider on JBoss 4.0.4 and JBoss 6.1.0 and exectuing extremely basic Java programs to send and receive messages and seeing what the perfomance is like in both environments. I hope that's clear enough.


                        I hear what you're saying about a false comparison. But out of the box, without configuring either JBossMQ or HornetQ, and running a JMS test program from page 1 of any JMS book, HornetQ is considerably slower than JBossMQ.

                         

                        I just meant to tell you you were missing the point.. and quite frankly you are still missing the point.

                         

                         

                        Why should I deliver a message system that only works on fake benchmarks? What kind of user would be interested in such products?

                         

                        If you don't provide some real data to the convesation your conversation will become just trolling.. and I believe/hope that's not your intention.

                         

                        I will continue this conversation when you provide me some real data. Saying JBoss MQ is faster then HornetQ without any data is just a bad joke and you are not even considering the possibility of the problem being on JBoss MQ (which I said about three times here and you tend to ignore)

                        • 9. Re: HornetQ is 15 times slower than JBossMQ !
                          petal1 Newbie

                          Hi Justin,

                           

                          I've cut a lot of the noise out the programs to minimise this post, but everything that is relevant is there.

                           

                          The reciever program takes a parameter to drive the scenarios I mentioned in my previous post:

                                    JBOSSMQ1 - MessageListener processes the messages. No need for the while/true loop because of the thread suppied by JBossMQ.

                                    HORNETQ1 - MessageListener processes the messages. while/true loop to prevent program exiting.

                                    JBOSSMQ2 - No MessageListener set. MessageConsumer.receive(0) processes the messages [listen2 method]

                                    HORNETQ2 - No MessageListener set. MessageConsumer.receive(0) processes the messages [listen2 method]

                           

                           

                          Sender program

                          ==============

                           

                              private Connection          m_connection = null;

                              private Session          m_session = null;

                              private MessageProducer          m_sender;

                              private Hashtable<String,String>          m_jndiProperties = new Hashtable<String,String>();

                           

                              public JMSSender()

                              {

                                  m_jndiProperties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");

                                  m_jndiProperties.put(javax.naming.Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

                                  m_jndiProperties.put(javax.naming.Context.PROVIDER_URL, "jnp://localhost:1099");

                           

                                  connectToResource();

                              }

                           

                              private void connectToResource()

                              {

                                  InitialContext context;

                                  ConnectionFactory connectionFactory;

                                  Destination destination = null;

                           

                                  try

                                  {

                                      context = new InitialContext(m_jndiProperties);

                           

                                      connectionFactory = (ConnectionFactory)context.lookup("ConnectionFactory");

                                      destination = (Destination)context.lookup("queue/myQueue");

                           

                                      m_connection = connectionFactory.createConnection();

                           

                                      m_session = m_connection.createSession(false, 1);          //AUTO_ACKNOWLEDGE

                                      m_sender = m_session.createProducer(destination);

                                  }

                                  catch (Throwable throwable)

                                  {

                                      throwable.printStackTrace();

                                  }

                              }

                             

                              private void runTest()

                              {

                                  while(testForLoopEnd() == false)

                                  {

                                      TextMessage tm = createJMSTextMessage();

                                     

                                      // end loop controls are updated here

                           

                           

                                      sendMessage(tm);

                                    }

                              }

                           

                           

                              private void sendMessage(TextMessage tm)

                              {

                                  try

                                  {

                                      tm.clearBody();

                                      tm.clearProperties();

                                      tm.setText("some text");

                           

                           

                                      m_sender.send(tm);

                                  }

                                  catch (JMSException e)

                                  {

                                      e.printStackTrace();

                                  }

                              }

                           

                           

                          There are actually 5 threads sending, but that's not important.

                           

                           

                              for (int i = 0; i < NUM_OF_THREADS; i++)

                              {

                                  final int j = i;

                           

                                  new Thread("T" +i) {

                                      public void run()

                                      {

                                          try

                                          {

                                              new JMSQueueSender().runTest();

                                          }

                                          catch (Throwable e)

                                          {

                                              e.printStackTrace();

                                          }

                                      }

                                  }.start();

                              }

                           

                           

                          Receiver program

                          ================

                           

                          public class JMSMessageListener implements MessageListener

                          {

                              private Connection          m_connection = null;

                              protected Session          m_session = null;

                              protected          MessageConsumer          m_consumer;

                           

                              private int m_implementationType = -1;

                           

                              protected Hashtable<String,String>          m_jndiProperties = new Hashtable<String,String>();

                           

                              public JMSMessageListener(int implType)

                              {

                                  m_implementationType = implType;

                           

                                  m_jndiProperties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");

                                  m_jndiProperties.put(javax.naming.Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

                                  m_jndiProperties.put(javax.naming.Context.PROVIDER_URL, "jnp://localhost:1099");

                           

                                  connectToResource();

                              }

                           

                              protected void connectToResource()

                              {

                                  InitialContext context;

                                  ConnectionFactory connectionFactory;

                                  Destination destination = null;

                           

                                  try

                                  {

                                      context = new InitialContext(m_jndiProperties);

                                      connectionFactory = (ConnectionFactory)context.lookup("ConnectionFactory");

                                      destination = (Destination)context.lookup("queue/myQueue");

                                      m_connection = connectionFactory.createConnection();

                                      m_session = m_connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

                                      m_consumer = m_session.createConsumer(destination);

                                      if (m_implementationType == HORNETQ1 || m_implementationType == JBOSSMQ1)

                                      {

                                          m_consumer.setMessageListener(this);

                                      }

                                  }

                                  catch (Throwable throwable)

                                  {

                                      throwable.printStackTrace();

                                  }

                              }

                           

                              public void run()

                              {

                                  try

                                  {

                                            m_connection.start();

                                            System.out.println("Listening...");

                                  }

                                  catch (JMSException e)

                                        {

                                      e.printStackTrace();

                                  }

                             

                                  if (m_implementationType == HORNETQ1)

                                  {

                                      listen1();

                                  }

                                  else if (m_implementationType == HORNETQ2 || m_implementationType == JBOSSMQ2)

                                  {

                                      listen2();

                                  }

                              }

                             

                              private void listen1()

                              {

                                  while (true) {

                                       // just keeping main thread alive

                                  }

                              }

                           

                              private void listen2()

                              {

                                  TextMessage message;

                           

                                  try

                                  {

                                      while (true)

                                      {

                                          Message m = m_consumer.receive(0);

                                          if (m != null)

                                          {

                                               message = (TextMessage) m;

                                               System.out.println("Received message: " + message.getText());

                                          }

                                      }

                                  }

                                  catch (Exception e)

                                  {

                                      e.printStackTrace();

                                  }

                              }

                             

                              public void onMessage(Message message)

                              {

                                  try

                                  {

                                      TextMessage tm = (TextMessage)message;

                                      String text = tm.getText();

                                      System.out.println("Received: " +text);

                                  }

                                  catch (JMSException e)

                                  {

                                      e.printStackTrace();

                                  }

                              }

                           

                              public static void main(String[] args)

                              {

                                  JMSMessageListener listener = new JMSMessageListener(implType);

                                  listener.run();

                              }

                          }

                          • 10. Re: HornetQ is 15 times slower than JBossMQ !
                            Clebert Suconic Master

                            Why are you doing this kind of loop here to burn CPU?

                             

                            Use some sort of sleep here.. while(true) {   Thread.sleep(10000); }

                                private void listen1()

                                {

                                    while (true) {

                                         // just keeping main thread alive

                                    }

                                }

                             

                                private void listen2()

                                {

                                    TextMessage message;

                             

                                    try

                                    {

                                        while (true)

                                        {

                                            Message m = m_consumer.receive(0);

                                            if (m != null)

                                            {

                                                 message = (TextMessage) m;

                                                 System.out.println("Received message: " + message.getText());

                                            }

                                        }

                                    }

                                    catch (Exception e)

                                    {

                                        e.printStackTrace();

                                    }

                                }

                              

                             

                             

                             

                            Why don't u use the same method for both anyways?

                             

                             

                            And anyways.. as I told you.. I don't think JBoss MQ is guaranteeing you syncs.. especially out of the box with HSQL. If you want real comparisons use a real database on JBoss MQ and make it perform syncs on committs. That's not really a valid comparisson.

                             

                             

                            Also the loop you are doing will diverge CPU into an empty loop. Maybe Java will do something to optimize with a block instead it but I would use a sleep just in case.

                            • 11. Re: HornetQ is 15 times slower than JBossMQ !
                              petal1 Newbie

                              Clebert,

                               

                              I have been running with JBossMQ for several years without any real issue. I'm not sure why you say the "problem" is on JBossMQ. What problem? I'm really not sure what you're missing.

                               

                              I think what you're trying to say is that if JBossMQ had the same functionality as HornetQ then JBossMQ would be slower. That may be the case. As I've said, I will run a test with the two settings you mentioned earlier as that appears to be what you are saying will bring HornetQ down to the functional level of JBossMQ.

                               

                              But at the moment, I have messages being successfully delivered by JBossMQ significantly faster than HornetQ in every test run. Fact. Believe me, that's not the result I was hoping for.

                              • 12. Re: HornetQ is 15 times slower than JBossMQ !
                                petal1 Newbie

                                Why are you doing this kind of loop here to burn CPU?

                                Use some sort of sleep here.. while(true) {   Thread.sleep(10000); }

                                 

                                - yeah, did that. That test is not the one I am comparing anyway as the results were so bad that it was clear the while/true loop was resulting in an unfair test. The MessageConsumer comparison is the one I have been referring to, and that does appear to be a fair comparison, the other matters not withstanding.

                                 

                                We use MySQL in production with JBossMQ. I can make that change to the JBossMQ test scenario, as well as the two settings, if it will make a fairer comparison?

                                Does HornetQ have a database behind it (like the jms_messages etc table in JBossMQ)?

                                • 13. Re: HornetQ is 15 times slower than JBossMQ !
                                  Clebert Suconic Master

                                  petal1 wrote:

                                   

                                  Clebert,

                                   

                                  I have been running with JBossMQ for several years without any real issue. I'm not sure why you say the "problem" is on JBossMQ. What problem? I'm really not sure what you're missing.

                                   

                                  I think what you're trying to say is that if JBossMQ had the same functionality as HornetQ then JBossMQ would be slower. That may be the case. As I've said, I will run a test with the two settings you mentioned earlier as that appears to be what you are saying will bring HornetQ down to the functional level of JBossMQ.

                                   

                                  But at the moment, I have messages being successfully delivered by JBossMQ significantly faster than HornetQ in every test run. Fact. Believe me, that's not the result I was hoping for.

                                  that's the last time I tell you this...  JBoss MQ with HSQL doesn't block on syncs... you are not guaranteeing syncs... If you're fine with that.. disable block on HornetQ.. I'm not going to repeat myself here.

                                   

                                  If you think Jboss MQ is faster under a valid scenario and you are ignoring everything I said.. there's nothing I can do here.   If you don't want blocking.. just disable blocking or persistency altogether.

                                  • 14. Re: HornetQ is 15 times slower than JBossMQ !
                                    Justin Bertram Master

                                    That test is not the one I am comparing anyway as the results were so bad that it was clear the while/true loop was resulting in an unfair test.

                                    I'm a little confused.  It seems like you're saying that the code you provided here is not actually the code you're using in your benchmark.  Is that true?  If so, why did you provide it here?

                                     

                                     

                                    We use MySQL in production with JBossMQ. I can make that change to the JBossMQ test scenario, as well as the two settings, if it will make a fairer comparison?

                                    I do think using MySQL in your benchmarking of JBossMQ would be more fair if you can ensure that MySQL is syncing to disk on every insert/delete.  As it stands now you're using Hypersonic which doesn't sync to disk on every insert/delete.  In fact, the version of Hypersonic included in JBoss AS 4.0.4 is more akin to a toy database (no offense to the authors of HSQLDB).

                                     

                                    Quick question...In your production environment is MySQL physically located on the same box as JBoss AS?

                                     

                                     

                                    Does HornetQ have a database behind it (like the jms_messages etc table in JBossMQ)?

                                    No.  HornetQ uses a local journal file rather than a database.

                                    1 2 Previous Next