11 Replies Latest reply on Feb 2, 2013 9:53 AM by alex75

    High CPU usage due to QueueImpl Runnable modifying checkDirect by ScheduledExecutorService

    alex75

      We're using HornetQ (2.2.14.Final) and having a high amount of clients connection to HornetQ server. When we've got about 10000 topic subscriptions for every subscription an instance of org.hornetq.core.server.impl.QueueImpl is created and every instance is scheduling following runnable in the configured scheduled ThreadPool:

      checkQueueSizeFuture = scheduledExecutor.scheduleWithFixedDelay(new Runnable()

      {

          public void run()

          {

             // This flag is periodically set to true. This enables the directDeliver flag to be set to true if the queue

             // is empty

             // We don't want to evaluate that on every delivery since that's too expensive

        

             checkDirect = true;

          }

      }, CHECK_QUEUE_SIZE_PERIOD, CHECK_QUEUE_SIZE_PERIOD, TimeUnit.MILLISECONDS);

       

      So for every subscription every 100ms this Runnable is executed and scheduled again. Because of this we've seen a high CPU load at our server machines even when we've configured every netty acceptor using direct-deliver=false to get a high throughput.

      You can easily try to reproduce this outside of HornetQ by following test code:

      import java.util.concurrent.Executors;

      import java.util.concurrent.ScheduledExecutorService;

      import java.util.concurrent.TimeUnit;

       

      public class CPULoadTest

      {

          private static final int PERIOD = 100;

          private static boolean myBoolean = false;

          private static ScheduledExecutorService scheduledExec = Executors.newScheduledThreadPool(5);

       

          public static void main(String[] Ps_args)

          {

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

              {

                  System.out.println("scheduling #" + i);

                  scheduledExec.scheduleWithFixedDelay(new Runnable()

                  {

                      @Override

                      public void run()

                      {

                          myBoolean = true;

                      }

                  }, PERIOD, PERIOD, TimeUnit.MILLISECONDS);

              }

          }

      }

       

      By modifying the PERIOD to 10000 ms the CPU load is nearly going to 0% CPU load.

      Because the interval CHECK_QUEUE_SIZE_PERIOD of the runnable isn't customizeable I don't know how to solve this performance problem.

       

      Can you please give me an advice what to do? Or are we really using HornetQ with too many subscriptions?