Thanuja
Thanuja

Reputation: 433

Performance concrens with RabbitMQ in multi-threaded environemnt

I have two simple test cases. In the first one I'm reusing both connection and channel. In the second one I'm reusing only the connection. Reason for having the second one is just to simulate channel per thread scenario in multi-threaded environment(this is not exactly same, but we can get an idea about the performance)

So from the first one I can publish 70000 msg/sec and from the second I can publish only 1500 msg/sec.

  1. Does this mean channel creation is costly in RabbitMQ?
  2. Can we use channel pooling to resolve this?

1st Sample

public class Send {

public static void main(String[] args) throws Exception {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.exchangeDeclare("myExchange", "direct", true);
    channel.queueDeclare("myQueue", true, false, false, null);

    for (int i = 0; i < 1000000; i++) {
        String message = "{\"id\" : \"56664f85-62e0-11e5-a74b-59530fbb6d8d\"" + i + "}";
        channel.basicPublish("", "myQueue", null, message.getBytes("UTF-8"));
    }

    channel.close();
    connection.close(); }

2nd Sample

public class Send {

public static void main(String[] args) throws Exception {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();

    for (int i = 0; i < 1000000; i++) {
        Channel channel = connection.createChannel();
        channel.exchangeDeclare("myExchange", "direct", true);
        channel.queueDeclare("myQueue", true, false, false, null);
        String message = "{\"id\" : \"56664f85-62e0-11e5-a74b-59530fbb6d8d\"" + i + "}";
        channel.basicPublish("", "myQueue", null, message.getBytes("UTF-8"));
        channel.close();
    }

    connection.close();
}

Upvotes: 0

Views: 120

Answers (1)

Gabriele Santomaggio
Gabriele Santomaggio

Reputation: 22682

I made a simple test:

 final int perfFor = 100000;
        d1 = new Date();
        for (int i = 0; i < perfFor; i++) {
            Channel channel1 = connection.createChannel();
            channel1.close();

        }
        d2 = new Date();
        seconds = (d2.getTime() - d1.getTime()) / 1000;
        System.out.println("Seconds-Only-CreateDestroyChannels: " + seconds);


        final AtomicInteger atomicInteger = new AtomicInteger();
        ExecutorService threadChannels = Executors.newFixedThreadPool(1000);
        final Date dThread = new Date();
        for (int i = 0; i < perfFor; i++) {

            threadChannels.submit(new Runnable() {
                public void run() {
                    Channel channel1 = null;
                    try {
                        channel1 = connection.createChannel();
                        channel1.close();
                        if (atomicInteger.addAndGet(1) == perfFor) {
                            Date d2 = new Date();
                            long seconds = (d2.getTime() - dThread.getTime()) / 1000;
                            System.out.println("Seconds-Only-CreateDestroyChannels MultiThreads: " + seconds);
  ...

I got this results:

Seconds-Only-CreateDestroyChannels: 84
Seconds-Only-CreateDestroyChannels MultiThreads: 59

So, I don't think you need to create a Channels pool. You should have a channel for thread, it means you start you thread and create the Channel.

channel.exchangeDeclare and channel.queueDeclare should be called just one time and not for each publish.

You also should consider to increase the Connection number, 1.000.000 for single Connection seems a bit unbalanced.

I suggest to read also this and this

RabbitMQ has lot ways to improve the performance, and you should consider all your environment and not just about the Channels .

hope it helps

Upvotes: 2

Related Questions