You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by David Sitsky <si...@nuix.com> on 2008/02/05 22:28:38 UTC

Trimming pending message cursors - big performance improvement

Hi,

In my application using the current trunk version, I was finding that my 
queue subscriptions had huge pending message cursors sizes (> 70,000 and 
growing) - essentially they were equal to enqueueCounter - 
dispatchCounter which I could see from JMX.

It seems like a simple optimisation could be to remove a node from the 
cursor if has been dropped when we call dispatchPending().  This made a 
gigantic difference in speed, since the broker wasn't iterating over a 
huge number of dropped messages, and locks were held for a shorter 
period of time.  Not to mention, less memory and CPU will be consumed by 
the broker.

Here is the patch below - I don't know if it is safe in general, but it 
seemed to work fine for me.

Cheers,
David

Index: 
activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java
===================================================================
--- 
activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java 
(revision 618650)
+++ 
activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java 
(working copy)
@@ -453,7 +461,11 @@
                              if (node == null) {
                                  break;
                              }
-                            if (canDispatch(node)) {
+			    else if (((QueueMessageReference)node).isDropped())
+			    {
+				pending.remove();
+			    }
+                            else if (canDispatch(node)) {
                                  pending.remove();
                                  // Message may have been sitting in 
the pending
                                  // list a while waiting for the 
consumer to ak the message.

Re: Trimming pending message cursors - big performance improvement

Posted by Rob Davies <ra...@gmail.com>.
Hi David,

I'll give it a whirl!

cheers,

Rob
On Feb 5, 2008, at 9:28 PM, David Sitsky wrote:

> Hi,
>
> In my application using the current trunk version, I was finding  
> that my queue subscriptions had huge pending message cursors sizes  
> (> 70,000 and growing) - essentially they were equal to  
> enqueueCounter - dispatchCounter which I could see from JMX.
>
> It seems like a simple optimisation could be to remove a node from  
> the cursor if has been dropped when we call dispatchPending().  This  
> made a gigantic difference in speed, since the broker wasn't  
> iterating over a huge number of dropped messages, and locks were  
> held for a shorter period of time.  Not to mention, less memory and  
> CPU will be consumed by the broker.
>
> Here is the patch below - I don't know if it is safe in general, but  
> it seemed to work fine for me.
>
> Cheers,
> David
>
> Index: activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java
> ===================================================================
> --- activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java (revision 618650)
> +++ activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java (working copy)
> @@ -453,7 +461,11 @@
>                             if (node == null) {
>                                 break;
>                             }
> -                            if (canDispatch(node)) {
> +			    else if (((QueueMessageReference)node).isDropped())
> +			    {
> +				pending.remove();
> +			    }
> +                            else if (canDispatch(node)) {
>                                 pending.remove();
>                                 // Message may have been sitting in  
> the pending
>                                 // list a while waiting for the  
> consumer to ak the message.


Re: Trimming pending message cursors - big performance improvement

Posted by David Sitsky <si...@nuix.com>.
While we are on this topic - are there any further optimisations that 
can be done?  What about messages which have already been acked?  I 
assume they have to be left in the list in case a transaction is 
rolled-back and the message has to be re-delivered, or is that not the 
case?  I haven't read enough of the code to find out.

In my application, I have some very long-running transactions, and it 
would be great to make the pending message cursor list as small as 
possible so that when dispatchPending() is called, it isn't performing a 
lot of redundant computation over and over again.

Cheers,
David

David Sitsky wrote:
> Hi,
> 
> In my application using the current trunk version, I was finding that my 
> queue subscriptions had huge pending message cursors sizes (> 70,000 and 
> growing) - essentially they were equal to enqueueCounter - 
> dispatchCounter which I could see from JMX.
> 
> It seems like a simple optimisation could be to remove a node from the 
> cursor if has been dropped when we call dispatchPending().  This made a 
> gigantic difference in speed, since the broker wasn't iterating over a 
> huge number of dropped messages, and locks were held for a shorter 
> period of time.  Not to mention, less memory and CPU will be consumed by 
> the broker.
> 
> Here is the patch below - I don't know if it is safe in general, but it 
> seemed to work fine for me.
> 
> Cheers,
> David
> 
> Index: 
> activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java 
> 
> ===================================================================
> --- 
> activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java 
> (revision 618650)
> +++ 
> activemq-core/src/main/java/org/apache/activemq/broker/region/PrefetchSubscription.java 
> (working copy)
> @@ -453,7 +461,11 @@
>                              if (node == null) {
>                                  break;
>                              }
> -                            if (canDispatch(node)) {
> +                else if (((QueueMessageReference)node).isDropped())
> +                {
> +                pending.remove();
> +                }
> +                            else if (canDispatch(node)) {
>                                  pending.remove();
>                                  // Message may have been sitting in the 
> pending
>                                  // list a while waiting for the 
> consumer to ak the message.


Re: Trimming pending message cursors - big performance improvement

Posted by Rob Davies <ra...@gmail.com>.
Will need to change this slightly - or durable topic subscribers will  
barf

On Feb 5, 2008, at 9:28 PM, David Sitsky wrote:

> Hi,
>
> In my application using the current trunk version, I was finding  
> that my queue subscriptions had huge pending message cursors sizes  
> (> 70,000 and growing) - essentially they were equal to  
> enqueueCounter - dispatchCounter which I could see from JMX.
>
> It seems like a simple optimisation could be to remove a node from  
> the cursor if has been dropped when we call dispatchPending().  This  
> made a gigantic difference in speed, since the broker wasn't  
> iterating over a huge number of dropped messages, and locks were  
> held for a shorter period of time.  Not to mention, less memory and  
> CPU will be consumed by the broker.
>
> Here is the patch below - I don't know if it is safe in general, but  
> it seemed to work fine for me.
>
> Cheers,
> David
>
> Index: activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java
> ===================================================================
> --- activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java (revision 618650)
> +++ activemq-core/src/main/java/org/apache/activemq/broker/region/ 
> PrefetchSubscription.java (working copy)
> @@ -453,7 +461,11 @@
>                             if (node == null) {
>                                 break;
>                             }
> -                            if (canDispatch(node)) {
> +			    else if (((QueueMessageReference)node).isDropped())
> +			    {
> +				pending.remove();
> +			    }
> +                            else if (canDispatch(node)) {
>                                 pending.remove();
>                                 // Message may have been sitting in  
> the pending
>                                 // list a while waiting for the  
> consumer to ak the message.