[activemq-dev] ActiveMQ memory usage, in simple test case

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[activemq-dev] ActiveMQ memory usage, in simple test case

CLAYTON, Neil , FM
Hi all,

It appears that ActiveMQ is leaking memory.
The test below mimics what Spring would do, using an JmsTemplate - in that
it'll create a new producer for each message being sent.  

I know this is not efficient, but at least it does serve a purpose in
terms of being a really fast way to show up this problem.

From what I can tell by looking at the code, it has to do with the caching
being enabled on the message writer being used (in this case, an
ActiveMQTextMessageWriter). Here is the relevant code from writePacket(...)

        if (cachingEnabled) {
         dataOut.writeShort(wireFormat.getWriteCachedKey(
               msg.getJMSClientID()));
         dataOut.writeShort(wireFormat.
               getWriteCachedKey(msg.getProducerKey()));
         if (cachingDestination){
               ****
                  dataOut.writeShort(wireFormat.
                           getWriteCachedKey(destination));


I have put '****' above the line that calls the method which writes data
into the DefaultWireFormat cache. The same wire format is used for each
message. But they keys differ. It appears that the keys are per producer?  
I'm not really sure.

In the digging I've done - I see no way to disable the caching either. The
transport gets it's own copy of the 'isCachingEnabled' flag from the wire format
. I tried setting up a custom wire format (and disabling the caching) to see if
this would have an effect, but it does not. It turns out that this is the case
because the transport is constructed with a copy of the wire format, but the
problem there is that DefaultWireFormat.copy doesn't actually copy anything at
all - it just creates a brand new default wire format object!

As you can see, I'm kinda struggling to make sense of it all.
Can someone confirm that this is a bug? or have I set up something incorreclty?
 I'm happy to do more debugging if required as well.

Finally, if you DONT create a producer for each message, the memory leak problem
does not occur - or rather, maybe it does - but it occurs more slowly. So far,
I've run the test for about 24 hours and found memory used to be up to 2M
(started at 1M and was stable at that level for at least 1 hr the day before).

Regards,
Neil Clayton


Testcase
----------
    public void testActiveMQMemoryUsage() throws Exception {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setUseEmbeddedBroker(false);
        factory.setBrokerURL("tcp://localhost:12121");
        Connection connection = factory.createConnection();

        Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
        Destination topic = session.createTopic("t1");
        connection.start();

        int msgCount = 0;

        while (true) {
            MessageProducer producer = session.createProducer(topic);
            TextMessage message = session.createTextMessage();
            message.setText("The time is now " +
                            System.currentTimeMillis());
            producer.send(message, DeliveryMode.NON_PERSISTENT, 1, 500);
            producer.close();

            msgCount++;
            if (msgCount % 1000 == 0) {
                monitorMemory();
            }
        }
    }


    private void monitorMemory() throws InterruptedException, JMSException {
        Runtime runtime = Runtime.getRuntime();
        System.out.println("Free: " + runtime.freeMemory() / 1024 / 1024 +
"MB,total: " + runtime.totalMemory() / 1024 / 1024 +
"MB, max: " + runtime.maxMemory() / 1024 / 1024 + "MB");
    }

Reply | Threaded
Open this post in threaded view
|

Re: [activemq-dev] ActiveMQ memory usage, in simple test case

chirino
Hi Neil,

I've opened up http://jira.logicblaze.com/jira/browse/AMQ-272 and  
http://jira.logicblaze.com/jira/browse/AMQ-273 to track your reported  
issues.

Regards,
Hiram

On Jun 21, 2005, at 4:05 AM, Neil Clayton wrote:

> Hi all,
>
> It appears that ActiveMQ is leaking memory.
> The test below mimics what Spring would do, using an JmsTemplate -  
> in that
> it'll create a new producer for each message being sent.
>
> I know this is not efficient, but at least it does serve a purpose in
> terms of being a really fast way to show up this problem.
>
>
>> From what I can tell by looking at the code, it has to do with the  
>> caching
>>
> being enabled on the message writer being used (in this case, an
> ActiveMQTextMessageWriter). Here is the relevant code from  
> writePacket(...)
>
>         if (cachingEnabled) {
>          dataOut.writeShort(wireFormat.getWriteCachedKey(
>                msg.getJMSClientID()));
>          dataOut.writeShort(wireFormat.
>                getWriteCachedKey(msg.getProducerKey()));
>          if (cachingDestination){
>                ****
>                   dataOut.writeShort(wireFormat.
>                            getWriteCachedKey(destination));
>
>
> I have put '****' above the line that calls the method which writes  
> data
> into the DefaultWireFormat cache. The same wire format is used for  
> each
> message. But they keys differ. It appears that the keys are per  
> producer?
> I'm not really sure.
>
> In the digging I've done - I see no way to disable the caching  
> either. The
> transport gets it's own copy of the 'isCachingEnabled' flag from  
> the wire format
> . I tried setting up a custom wire format (and disabling the  
> caching) to see if
> this would have an effect, but it does not. It turns out that this  
> is the case
> because the transport is constructed with a copy of the wire  
> format, but the
> problem there is that DefaultWireFormat.copy doesn't actually copy  
> anything at
> all - it just creates a brand new default wire format object!
>
> As you can see, I'm kinda struggling to make sense of it all.
> Can someone confirm that this is a bug? or have I set up something  
> incorreclty?
>  I'm happy to do more debugging if required as well.
>
> Finally, if you DONT create a producer for each message, the memory  
> leak problem
> does not occur - or rather, maybe it does - but it occurs more  
> slowly. So far,
> I've run the test for about 24 hours and found memory used to be up  
> to 2M
> (started at 1M and was stable at that level for at least 1 hr the  
> day before).
>
> Regards,
> Neil Clayton
>
>
> Testcase
> ----------
>     public void testActiveMQMemoryUsage() throws Exception {
>         ActiveMQConnectionFactory factory = new  
> ActiveMQConnectionFactory();
>         factory.setUseEmbeddedBroker(false);
>         factory.setBrokerURL("tcp://localhost:12121");
>         Connection connection = factory.createConnection();
>
>         Session session = connection.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
>         Destination topic = session.createTopic("t1");
>         connection.start();
>
>         int msgCount = 0;
>
>         while (true) {
>             MessageProducer producer = session.createProducer(topic);
>             TextMessage message = session.createTextMessage();
>             message.setText("The time is now " +
>                             System.currentTimeMillis());
>             producer.send(message, DeliveryMode.NON_PERSISTENT, 1,  
> 500);
>             producer.close();
>
>             msgCount++;
>             if (msgCount % 1000 == 0) {
>                 monitorMemory();
>             }
>         }
>     }
>
>
>     private void monitorMemory() throws InterruptedException,  
> JMSException {
>         Runtime runtime = Runtime.getRuntime();
>         System.out.println("Free: " + runtime.freeMemory() / 1024 /  
> 1024 +
> "MB,total: " + runtime.totalMemory() / 1024 / 1024 +
> "MB, max: " + runtime.maxMemory() / 1024 / 1024 + "MB");
>     }
>

Reply | Threaded
Open this post in threaded view
|

Re: [activemq-dev] ActiveMQ memory usage, in simple test case

chirino
Hi Neil,


The problem should now be fixed in our latest 3.1-SNAPSHOT:
http://dist.codehaus.org/activemq/distributions/activemq-3.1- 
SNAPSHOT.zip
http://dist.codehaus.org/activemq/distributions/activemq-3.1- 
SNAPSHOT.tar.gz

Could you confirm that this fixes the problem for you?

Thanks,
Hiram

On Jun 22, 2005, at 9:35 AM, Hiram Chirino wrote:

> Hi Neil,
>
> I've opened up http://jira.logicblaze.com/jira/browse/AMQ-272 and  
> http://jira.logicblaze.com/jira/browse/AMQ-273 to track your  
> reported issues.
>
> Regards,
> Hiram
>
> On Jun 21, 2005, at 4:05 AM, Neil Clayton wrote:
>
>
>> Hi all,
>>
>> It appears that ActiveMQ is leaking memory.
>> The test below mimics what Spring would do, using an JmsTemplate -  
>> in that
>> it'll create a new producer for each message being sent.
>>
>> I know this is not efficient, but at least it does serve a purpose in
>> terms of being a really fast way to show up this problem.
>>
>>
>>
>>> From what I can tell by looking at the code, it has to do with  
>>> the caching
>>>
>>>
>> being enabled on the message writer being used (in this case, an
>> ActiveMQTextMessageWriter). Here is the relevant code from  
>> writePacket(...)
>>
>>         if (cachingEnabled) {
>>          dataOut.writeShort(wireFormat.getWriteCachedKey(
>>                msg.getJMSClientID()));
>>          dataOut.writeShort(wireFormat.
>>                getWriteCachedKey(msg.getProducerKey()));
>>          if (cachingDestination){
>>                ****
>>                   dataOut.writeShort(wireFormat.
>>                            getWriteCachedKey(destination));
>>
>>
>> I have put '****' above the line that calls the method which  
>> writes data
>> into the DefaultWireFormat cache. The same wire format is used for  
>> each
>> message. But they keys differ. It appears that the keys are per  
>> producer?
>> I'm not really sure.
>>
>> In the digging I've done - I see no way to disable the caching  
>> either. The
>> transport gets it's own copy of the 'isCachingEnabled' flag from  
>> the wire format
>> . I tried setting up a custom wire format (and disabling the  
>> caching) to see if
>> this would have an effect, but it does not. It turns out that this  
>> is the case
>> because the transport is constructed with a copy of the wire  
>> format, but the
>> problem there is that DefaultWireFormat.copy doesn't actually copy  
>> anything at
>> all - it just creates a brand new default wire format object!
>>
>> As you can see, I'm kinda struggling to make sense of it all.
>> Can someone confirm that this is a bug? or have I set up something  
>> incorreclty?
>>  I'm happy to do more debugging if required as well.
>>
>> Finally, if you DONT create a producer for each message, the  
>> memory leak problem
>> does not occur - or rather, maybe it does - but it occurs more  
>> slowly. So far,
>> I've run the test for about 24 hours and found memory used to be  
>> up to 2M
>> (started at 1M and was stable at that level for at least 1 hr the  
>> day before).
>>
>> Regards,
>> Neil Clayton
>>
>>
>> Testcase
>> ----------
>>     public void testActiveMQMemoryUsage() throws Exception {
>>         ActiveMQConnectionFactory factory = new  
>> ActiveMQConnectionFactory();
>>         factory.setUseEmbeddedBroker(false);
>>         factory.setBrokerURL("tcp://localhost:12121");
>>         Connection connection = factory.createConnection();
>>
>>         Session session = connection.createSession(false,
>> Session.AUTO_ACKNOWLEDGE);
>>         Destination topic = session.createTopic("t1");
>>         connection.start();
>>
>>         int msgCount = 0;
>>
>>         while (true) {
>>             MessageProducer producer = session.createProducer(topic);
>>             TextMessage message = session.createTextMessage();
>>             message.setText("The time is now " +
>>                             System.currentTimeMillis());
>>             producer.send(message, DeliveryMode.NON_PERSISTENT, 1,  
>> 500);
>>             producer.close();
>>
>>             msgCount++;
>>             if (msgCount % 1000 == 0) {
>>                 monitorMemory();
>>             }
>>         }
>>     }
>>
>>
>>     private void monitorMemory() throws InterruptedException,  
>> JMSException {
>>         Runtime runtime = Runtime.getRuntime();
>>         System.out.println("Free: " + runtime.freeMemory() /  
>> 1024 / 1024 +
>> "MB,total: " + runtime.totalMemory() / 1024 / 1024 +
>> "MB, max: " + runtime.maxMemory() / 1024 / 1024 + "MB");
>>     }
>>
>

Reply | Threaded
Open this post in threaded view
|

[activemq-dev] Re: ActiveMQ memory usage, in simple test case

CLAYTON, Neil , FM
Hiram Chirino <hiram@...> writes:

>
> Hi Neil,
>
> The problem should now be fixed in our latest 3.1-SNAPSHOT:
> http://dist.codehaus.org/activemq/distributions/activemq-3.1- 
> SNAPSHOT.zip
> http://dist.codehaus.org/activemq/distributions/activemq-3.1- 
> SNAPSHOT.tar.gz
>
> Could you confirm that this fixes the problem for you?
>
> Thanks,
> Hiram
>
> On Jun 22, 2005, at 9:35 AM, Hiram Chirino wrote:
>


Yes, this seems to work well now.
thanks for the fix!

Uses up to 11Mb of memory, and then seems to sit at that level quite nicely.

Regards,
Neil Clayton