Friday, December 9, 2016

50K persistent messages per second on my laptop with Artemis

This is a guide to how to make your producers and consumers fly with Artemis


Many users have been using message systems that will favor performance instead of full guarantees of writes.

This is something we have been doing for years with the Artemis codebase, including Artemis and previous versions of HornetQ.

This is a small tutorial to do such thing with Artemis, pretty simple and quite powerful.

This will make sender to be 100% asynchronous, So you never block the producer and you can easily make thousands messages / second.

Even still the guarantees are quite high as the message will be persisted at the journal within milliseconds.

So, here is how you do it:

  • Disable Block on Persistent Messages:

There are two ways you can do that:

I - Disable blockOnDurableSend through a property:


ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
factory.setBlockOnDurableSend(false);



II - Disable blockOnDurableSend through the URI for the connection Factory:

ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?blockOnDurableSend=false);


  • Send non Transactionally:

A transaction means a hard sync on the world. Make a round trip to the server and sync on disk.
If you send a regular Persistent Message, asynchronously, then you get a large throughput on your producers.


Here is a full example:
package org.apache.activemq.artemis.cli.commands.messages;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

public class FastProducer {

   public static void main(String arg[]) {
      try {
         ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616?blockOnDurableSend=false");
         Connection connection = factory.createConnection();
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination queue = ActiveMQDestination.createDestination("queue://TEST", ActiveMQDestination.QUEUE_TYPE);
         MessageProducer producer = session.createProducer(queue);

         long time = System.currentTimeMillis();

         for (int i = 0; i < 100000; i++) {
            producer.send(session.createTextMessage("hello guys"));
         }

         System.out.println("Send message in " + (System.currentTimeMillis() - time) + " milliseconds");

         connection.close();
      }
      catch (Exception e) {

      }
   }
}

With this little example here I am able to send 100K messages in less than 2 seconds using my laptop.



Send message in 1772 milliseconds



And we are still improving things. Watch out for more improvements over the next month :)