1

We've performed a performance test with Oracle Advanced Queue on our Oracle DB environment. We've created the queue and the queue table with the following script:

    BEGIN

    DBMS_AQADM.create_queue_table(
          queue_table => 'verisoft.qt_test', 
          queue_payload_type => 'SYS.AQ$_JMS_MESSAGE', 
          sort_list => 'ENQ_TIME', 
          multiple_consumers => false, 
          message_grouping => 0, 
          comment =>  'POC Authorizations Queue Table - KK',
          compatible => '10.0', 
          secure => true);

    DBMS_AQADM.create_queue(
          queue_name => 'verisoft.q_test', 
          queue_table => 'verisoft.qt_test', 
          queue_type => dbms_aqadm.NORMAL_QUEUE, 
          max_retries => 10, 
          retry_delay => 0, 
          retention_time => 0, 
          comment => 'POC Authorizations Queue - KK'); 

    DBMS_AQADM.start_queue('q_test');
    END;

    /

We've published 1000000 messages with 2380 TPS using a PL/SQL client. And we've consumed 1000000 messages with 292 TPS, using Oracle JMS API Client. The consumer rate is almost 10 times slower than the publisher and that speed does not meet our requirements.

Below, is the piece of Java code that we use to consume messages:

    if (q == null) initializeQueue();
    System.out.println(listenerID + ": Listening on queue " + q.getQueueName() + "...");
    MessageConsumer consumer = sess.createConsumer(q);

    for (Message m; (m = consumer.receive()) != null;) {
        new Timer().schedule(new QueueExample(m), 0);
    }

    sess.close();
    con.close();

Do you have any suggestion on, how we can improve the performance at the consumer side?

Casper
  • 107
  • 2
  • 12

1 Answers1

0

Your use of Timer may be your primary issue. The Timer definition reads:

Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread. This can, in turn, delay the execution of subsequent tasks, which may "bunch up" and execute in rapid succession when (and if) the offending task finally completes.

I would suggest you use a ThreadPool.

// My executor.
ExecutorService executor = Executors.newCachedThreadPool();

public void test() throws InterruptedException {
    for (int i = 0; i < 1000; i++) {
        final int n = i;
        // Instead of using Timer, create a Runnable and pass it to the Executor.
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("Run " + n);
            }

        });

    }
    executor.shutdown();
    executor.awaitTermination(1, TimeUnit.DAYS);
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213