9 Replies Latest reply on Mar 10, 2004 7:14 PM by xibin

    Performance numbers

    speakmon

      Hi,

      I've got JBossMQ installed and running and it seems to work great. I've been testing it for performance and I was wondering if the numbers I'm seeing are typical or if they're wildly off.

      For a simple test program that involves sending 10000 persistent messages to a queue, I get rates of ~68 msgs/sec. (The host machine is a dual CPU PIII with 1GB RAM.) The numbers range from 63 to 69 msgs/sec.

      I'm thinking that JBossMQ can go much faster than this. If that's true, does anybody have any suggestions for things to look at in order to speed it up some? 100 msgs/sec is our goal for this application.

      Thanks in advance,
      --Ben

        • 1. Re: Performance numbers

          The numbers I get are (using local sockets):

          persistent 300 msgs/sec ~ 1 Million per hour
          non-persistent 3000 msgs/sec ~ 10 Million per hour

          This is using jdbc2/hsqldb as the persistence manager

          That is about what I would expect, about a
          factor of 10 between the serialize/don't serialize option.

          Regards,
          Adrian

          • 2. Re: Performance numbers

            Forgot to mention:

            1GHz single processor pentium III,
            java running with the default 64M ram.

            Regards,
            Adrian

            • 3. Re: Performance numbers
              speakmon

              Those numbers are more in line with what I expected. Is there any reason you can think of why mine would be so slow?

              I'm including the small test program I'm using. Am I doing something really silly? (I'm using the OIL2 ConnectionFactory).

              Thanks again,
              --Ben

              /*
              * JMSTester.java
              *
              * Created on June 23, 2003, 11:05 AM
              */

              import java.util.Date;
              import java.util.Hashtable;

              import javax.naming.*;
              import javax.jms.*;

              /**
              *
              * @author bspeakmo
              */
              public final class JMSTester {

              private static Context context;
              private static QueueConnectionFactory factory;
              private static QueueConnection queueConn;
              private static QueueSession qSession;
              private static Queue smsQueue;
              private static QueueSender sender;

              /** Creates a new instance of JMSTester */
              public JMSTester() {
              }

              /**
              * @param args the command line arguments
              */
              public static void main(String[] args) {
              try {
              Hashtable jndi = new Hashtable();
              jndi.put(Context.PROVIDER_URL, "jnp://localhost:9888/");
              jndi.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
              jndi.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces.NamingContextFactory");
              Context context = new InitialContext(jndi);
              System.out.println("JNDI context initialized");

              // get JMS objects and queues
              factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
              queueConn = factory.createQueueConnection();
              qSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
              smsQueue = (Queue) context.lookup("queue/sms_queue_mo_mobliss");
              sender = qSession.createSender(smsQueue);
              sender.setDeliveryMode(DeliveryMode.PERSISTENT);
              System.out.println("JMS connection established");

              System.out.println("Starting test run: " + new Date().toString());
              long start = System.currentTimeMillis();
              for (int i = 0; i < 10000; i++) {
              TextMessage textMsg = qSession.createTextMessage("test message");
              sender.send(textMsg);
              }
              System.out.println("Run complete: " + new Date().toString());
              long elapsedSeconds = (System.currentTimeMillis() - start) / 1000;
              System.out.println("Sent 10000 messages at " + ((float) 10000 / elapsedSeconds) + " msgs/sec");
              } catch (Exception e) {
              e.printStackTrace();
              }
              }

              }

              • 4. Re: Performance numbers
                genman


                It depends on your network needs, but I find the vanilla OIL service to be fastest for remote access. Also, performance depends on your persistance manager configuration, DB and/or filesystem and disks.

                I see you're from Mobliss, eh?

                • 5. Re: Performance numbers
                  speakmon

                  After another day of tweaking I'm still no closer. I've included relevant config below; am I doing anything wrong with Jboss?

                  Thanks very much,
                  --Ben

                  MSSQLDB-ds.xml:
                  ----------------------
                  <xa-datasource>
                  <jndi-name>MSSQLXADS</jndi-name>
                  <xa-datasource-class>com.jnetdirect.jsql.JSQLXADataSource</xa-datasource-class>
                  <xa-datasource-property name="ServerName">dbServerName</xa-datasource-property>
                  <xa-datasource-property name="Database">dbName</xa-datasource-property>
                  <user-name>dbUser</user-name>
                  dbPass
                  <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
                  <min-pool-size>5</min-pool-size>
                  <max-pool-size>100</max-pool-size>
                  <blocking-timeout-millis>5000</blocking-timeout-millis>
                  <idle-timeout-minutes>15</idle-timeout-minutes>
                  </xa-datasource>

                  jbossmq-service.xml:
                  ---------------------------
                  <?xml version="1.0" encoding="UTF-8"?>

                  <!-- $Id: jbossmq-service.xml,v 1.10.2.9 2003/04/24 12:51:10 ejort Exp $ -->



                  <!-- ==================================================================== -->
                  <!-- JBossMQ -->
                  <!-- ==================================================================== -->


                  <!-- ==================================================================== -->
                  <!-- Invocation Layers -->
                  <!-- ==================================================================== -->
                  <!--
                  | InvocationLayers are the different transport methods that can
                  | be used to access the server.
                  -->

                  <!--

                  <depends optional-attribute-name="Invoker">jboss.mq:service=Invoker
                  RMIConnectionFactory
                  RMIXAConnectionFactory
                  60000

                  -->

                  <!--

                  <depends optional-attribute-name="Invoker">jboss.mq:service=Invoker
                  ConnectionFactory
                  XAConnectionFactory
                  8090
                  60000
                  true

                  -->


                  <depends optional-attribute-name="Invoker">jboss.mq:service=Invoker
                  ConnectionFactory
                  XAConnectionFactory
                  8092
                  60000
                  true


                  <!--
                  New Unified Invocation Layer as of 3.0.7 - experimental
                  Synchronization moved to the message level to improve throughput
                  -->
                  <!--

                  <depends optional-attribute-name="Invoker">jboss.mq:service=Invoker
                  UIL2ConnectionFactory
                  UIL2XAConnectionFactory
                  8093
                  60000
                  true
                  -->
                  <!-- Used to disconnect the client if there is no activity -->
                  <!-- Ensure this is greater than the ping period -->
                  <!--70000-->
                  <!-- The size of the buffer (in bytes) wrapping the socket -->
                  <!-- The buffer is flushed after each request -->
                  <!--2048-->
                  <!-- Large messages may block the ping/pong -->
                  <!-- A pong is simulated after each chunk (in bytes) for both reading and writing -->
                  <!-- It must be larger than the buffer size -->
                  <!--
                  1000000

                  -->

                  <!--
                  | The HTTP IL is configured in the deploy directory and available by
                  | default in both the "default" and "all" server configurations. To customize
                  | its attributes please see the jboss-service.xml file included in
                  | the META-INF directory of jbossmq-httpil.sar directory. The rationale
                  | for not including its configuration here is due to the fact that it
                  | includes a required dependant web module which would have required
                  | a stand alone WAR file. It was elected, therefore, to put everything
                  | in the deploy directory.
                  -->

                  <!-- ==================================================================== -->
                  <!-- JBossMQ Interceptor chain configuration -->
                  <!-- ==================================================================== -->
                  <!-- To tune performance, you can have the Invoker skip over the TracingInterceptor -->
                  <!-- and/or the SecurityManager, but then you loose the ability to trace and/or enforce security. -->



                  <depends optional-attribute-name="NextInterceptor">jboss.mq:service=SecurityManager



                  <!--

                  org.jboss.mq.server.TracingInterceptor
                  <depends optional-attribute-name="NextInterceptor">jboss.mq:service=SecurityManager

                  -->


                  <depends optional-attribute-name="NextInterceptor">jboss.mq:service=DestinationManager



                  <!--
                  | The ClientMonitorInterceptor disconnects clients that have been idle for to long.
                  | This interceptor is not enabled by default since the server might disconnect clients
                  | when the it is under high load.
                  -->
                  <!--

                  80000
                  <depends optional-attribute-name="NextInterceptor">jboss.mq:service=ClientReconnectInterceptor

                  -->

                  <!--
                  | The ClientReconnectInterceptor is used to allow a client to connect to the server even
                  | if it's clientID is allready being used by another client. This interceptor will disconnect
                  | the previously connected client to allow the new connection to succeed. This is not enabled
                  | by default since the JMS spec states that the 2nd client connecting to the server with the same
                  | id should get an exception.
                  -->
                  <!--

                  org.jboss.mq.server.ClientReconnectInterceptor
                  <depends optional-attribute-name="NextInterceptor">jboss.mq:service=DestinationManager

                  -->


                  <depends optional-attribute-name="PersistenceManager">jboss.mq:service=PersistenceManager
                  <depends optional-attribute-name="StateManager">jboss.mq:service=StateManager


                  <!--
                  | The MessageCache decides where to put JBossMQ message that
                  | are sitting around waiting to be consumed by a client.
                  |
                  | The memory marks are in Megabytes. Once the JVM memory usage hits
                  | the high memory mark, the old messages in the cache will start getting
                  | stored in the DataDirectory. As memory usage gets closer to the
                  | Max memory mark, the amount of message kept in the memory cache aproaches 0.
                  |
                  | ATTENTION: When the "file" or "rollinglogged" Persistence Manager is used
                  | you have to set the "CacheStore" to the CacheStore (the commented out line)
                  | and not to the PM itself.
                  -->

                  128
                  196
                  <!--
                  <depends optional-attribute-name="CacheStore">jboss.mq:service=CacheStore
                  -->
                  jboss.mq:service=PersistenceManager



                  <!--
                  | The CacheStore decides where to store JBossMQ message that
                  | that the MessageCache has decided to move in secondary storage.
                  |
                  | Now you can specify a absolut path by using an ULR like:
                  | file:///c:/temp
                  | ATTENTION: the directory MUST exists because it will not be
                  | created.
                  -->

                  tmp/jbossmq


                  <!--
                  | The StateManager is used to keep JMS persistent state data.
                  | For example: what durable subscriptions are active.
                  -->

                  <!-- This file is pulled from the configuration URL of the server -->
                  jbossmq-state.xml


                  <!--
                  | The PersistenceManager is used to store messages to disk.
                  |
                  | Now you can specify a absolut path by using an ULR like:
                  | file:///c:/temp
                  | ATTENTION: the directory MUST exists because it will not be
                  | created. Also for the "file" Persistance Manager the directory
                  | MUST be empty otherwise the startup fails ("rollinglogged" works
                  | fine.
                  -->
                  <!--

                  data/jbossmq/file
                  <depends optional-attribute-name="MessageCache">jboss.mq:service=MessageCache

                  -->

                  <!--
                  | The jdbc2 PersistenceManager is the new improved JDBC implementation.
                  | This implementation allows you to control how messages are stored in
                  | the database.
                  |
                  | Use this PM if you want the reliablity a relational database can offer
                  | you. The default configuration is known to work with hsqldb, other databases
                  | will requrie teaking of the SqlProperties.
                  -->


                  <depends optional-attribute-name="MessageCache">jboss.mq:service=MessageCache
                  <!--
                  <depends optional-attribute-name="ConnectionManager">jboss.jca:service=LocalTxCM,name=MSSQLDS
                  -->
                  <depends optional-attribute-name="ConnectionManager">jboss.jca:service=XATxCM,name=MSSQLXADS


                  BLOB_TYPE=BYTES_BLOB
                  INSERT_TX = INSERT INTO JMS_TRANSACTIONS (TXID) values(?)
                  INSERT_MESSAGE = INSERT INTO JMS_MESSAGES (MESSAGEID, DESTINATION, MESSAGEBLOB, TXID, TXOP) VALUES(?,?,?,?,?)
                  SELECT_ALL_UNCOMMITED_TXS = SELECT TXID FROM JMS_TRANSACTIONS
                  SELECT_MAX_TX = SELECT MAX(TXID) FROM JMS_MESSAGES
                  SELECT_MESSAGES_IN_DEST = SELECT MESSAGEID, MESSAGEBLOB FROM JMS_MESSAGES WHERE DESTINATION=?
                  SELECT_MESSAGE = SELECT MESSAGEID, MESSAGEBLOB FROM JMS_MESSAGES WHERE MESSAGEID=? AND DESTINATION=?
                  MARK_MESSAGE = UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE MESSAGEID=? AND DESTINATION=?
                  UPDATE_MESSAGE = UPDATE JMS_MESSAGES SET MESSAGEBLOB=? WHERE MESSAGEID=? AND DESTINATION=?
                  UPDATE_MARKED_MESSAGES = UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE TXOP=?
                  UPDATE_MARKED_MESSAGES_WITH_TX = UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE TXOP=? AND TXID=?
                  DELETE_MARKED_MESSAGES_WITH_TX = DELETE FROM JMS_MESSAGES WHERE TXID IN (SELECT TXID FROM JMS_TRANSACTIONS) AND TXOP=?
                  DELETE_TX = DELETE FROM JMS_TRANSACTIONS WHERE TXID = ?
                  DELETE_MARKED_MESSAGES = DELETE FROM JMS_MESSAGES WHERE TXID=? AND TXOP=?
                  DELETE_MESSAGE = DELETE FROM JMS_MESSAGES WHERE MESSAGEID=? AND DESTINATION=?
                  CREATE_MESSAGE_TABLE = CREATE TABLE JMS_MESSAGES ( MESSAGEID INTEGER NOT NULL, \
                  DESTINATION VARCHAR(255) NOT NULL, TXID INTEGER, TXOP CHAR(1), \
                  MESSAGEBLOB IMAGE, PRIMARY KEY (MESSAGEID, DESTINATION) )
                  CREATE_TX_TABLE = CREATE TABLE JMS_TRANSACTIONS ( TXID INTEGER )



                  <!-- ==================================================================== -->
                  <!-- System Destinations -->
                  <!-- ==================================================================== -->

                  <!-- Dead Letter Queue -->

                  <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager
                  <!--<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager-->



                  • 6. Re: Performance numbers

                    The only difference I can see between your
                    test and mine is that you are creating the message
                    inside the loop.

                    On the configuration:
                    jdbc2 doesn't need an XA driver, it is implementing
                    the local branch operations of an XA transaction.

                    What numbers do you get if you use
                    the default hsqldb?

                    Regards,
                    Adrian

                    • 7. Re: Performance numbers
                      speakmon

                      Hi Adrian,

                      Thanks for the help!

                      I'm using the actual XADataSource driver because I wondered if the connection pooling that my driver supports would help performance any. Testing showed that it didn't.

                      I'll run against hsqldb in the morning and report results.

                      Thanks,
                      --Ben

                      • 8. Re: Performance numbers
                        speakmon

                        Results from this morning's testing:

                        (after moving the TextMessage creation outside of the sending loop)

                        MSSQL: ~101 msgs/sec
                        hsqldb: ~294 msgs/sec

                        Seems hsqldb is a lot faster. Not very surprising.

                        Thanks for your help, Adrian. I'm good to go here. :)

                        • 9. Re: Performance numbers for Oracle and MS SQL
                          xibin

                          I confirm the number with Hypersonic on JBoss3.2.2, which is about 300/s. I'm sending ObjectMessage with small objects to a queue, no subscribers.

                          However, I cannot get Oracle and MS SQL server to get even close to that number:

                          Oracle - 75 msgs/second
                          MS SQL - 50 msgs/second

                          Adrian, where should I go about improving this number? Our DBA changed the BLOB to be stored inline in the row....did not help much. I wanted to make sure that JBoss is using prepared statement. I looked at the mssql-jdbc2-service.xml and oracle-jdbc2-service.xml and it is not clear to me where to improve.

                          I got java.lang.OutOfMemory from Hypersonic when I tried to inject 20000 messages in a loop.

                          To give you some perspective, if I inserted the messages through JDBC directly using autocommit, I get 150 msgs/second. If I commited at the end of my insert loop, the numer jumps to 600 msgs/second. We sort of figured that JBoss JMS needs to commit for each message, so 150 msgs/second is probably the limit. But we are not getting that through JBoss JMS and jdbc2 PM.

                          Do you or anybody else have any suggestions on this subject?

                          Thanks
                          Xibin