STS grails junit memory leak

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

STS grails junit memory leak

cats

After a bit of googling, I've been unable to find anything about my particular problem so here goes...

I've been having some trouble with memory leaks running Junit tests against our STS grails project test/unit tests. I like to run it within eclipse so you get the green-bar, since its fast and easy, but I have had to bump the JVM settings up to -Xmx400m to keep things OK. I've had a bit a go at diagnosis wth Jprofiler, but although I've had success with this in the Java world, nothing leapt out at me.

Our application has gone live, and there are no problems in production (looks good under load in JBoss looking through jvisualvm at the heap), so I'm guessing the memory leak is isolated to the mockDomain mechanism used heavily in our unit tests, and/or the metaclass workarounds to improve some of the behaviour where the standard mockDomain doesn't quite do it. We've been diligent with setup() and tearDown() so I don't believe we are missing anything there. We've also had a good look at the hierarchy and helpers (e.g. MockUtil) so think that I know roughly how things are going, but since this is my first groovy/grails experience there's still a lot to learn.

We are into phase 2 of development of our grails project now, and I would like to add a whole lot more unit and integration tests, but am concerned about the leak.

Using STS 2.5.0, Grails 1.3.6.

Any thoughts, or similar experiences gratefully received,

Cheers!
Rob
Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

cats
OK, I got round to looking at this again yesterday (somewhat inspired by the fact that our hudson build was failing due to OOM :-))

It turns out that mockConfig() leaks like a sieve, and we were calling mockConfig() for a high percentage of our unit tests (we now have about 750). By default we were passing the Config.groovy file to this in setup like so:

        @Override
        protected void setUp() {
                super.setUp();
                mockConfig(new File( 'grails-app/conf/Config.groovy' ).text)
        }

Every time this was called it leaked a bit more until everything ground to a halt.
It seems that ConfigSlurper is the culprit underneath mockConfig() method.

In order to work around this I used a common superclass for unit tests in between us and GrailsUnitTestCase which does a one-time static cache of the ConfigObject. Once this is set, then our new mockConfig just reuses the cached ConfigObject rather than continually calling ConfigSlurper.

During debugging this, I also noted that if you use mockConfig to mock some snippet of code, then we were getting weird problems with the subsequent integration tests, where we need to simulate a user logging in to spring security. I guess somewhere in the static caching inside the ConfigurationHolder it was remembering the crippled notion of what a config was, and then this was affecting the subsequent integration tests.

Anyway, the single simple static cached ConfigObject seems to be the solution.
Moral of the story: do not make many multiple calls to ConfigSlurper.parse() or mockConfig() !

Yet again, Grails gives with one hand, and takes away with the other ...

Cheers!
Rob
Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

Andrew Eisenberg
Are you finding any differences when you run inside of STS vs when you
run on the command line.

On Fri, Feb 25, 2011 at 6:11 AM, cats <[hidden email]> wrote:

>
> OK, I got round to looking at this again yesterday (somewhat inspired by the
> fact that our hudson build was failing due to OOM :-))
>
> It turns out that mockConfig() leaks like a sieve, and we were calling
> mockConfig() for a high percentage of our unit tests (we now have about
> 750). By default we were passing the Config.groovy file to this in setup
> like so:
>
>        @Override
>        protected void setUp() {
>                super.setUp();
>                mockConfig(new File( 'grails-app/conf/Config.groovy' ).text)
>        }
>
> Every time this was called it leaked a bit more until everything ground to a
> halt.
> It seems that ConfigSlurper is the culprit underneath mockConfig() method.
>
> In order to work around this I used a common superclass for unit tests in
> between us and GrailsUnitTestCase which does a one-time static cache of the
> ConfigObject. Once this is set, then our new mockConfig just reuses the
> cached ConfigObject rather than continually calling ConfigSlurper.
>
> During debugging this, I also noted that if you use mockConfig to mock some
> snippet of code, then we were getting weird problems with the subsequent
> integration tests, where we need to simulate a user logging in to spring
> security. I guess somewhere in the static caching inside the
> ConfigurationHolder it was remembering the crippled notion of what a config
> was, and then this was affecting the subsequent integration tests.
>
> Anyway, the single simple static cached ConfigObject seems to be the
> solution.
> Moral of the story: do not make many multiple calls to ConfigSlurper.parse()
> or mockConfig() !
>
> Yet again, Grails gives with one hand, and takes away with the other ...
>
> Cheers!
> Rob
> --
> View this message in context: http://grails.1312388.n4.nabble.com/STS-grails-junit-memory-leak-tp3262084p3324486.html
> Sent from the Grails - user mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

cats
No difference, the STS bit was a red herring. The OOM happened in our Hudson build as well as within STS. The problem is pure groovy ... ConfigSlurper leaks, which may not be such a problem, but the grails mocking framework advertises mockConfig as suitable for purpose, which it is not.

What surprises me is that I would have thought a lot more people would have hit this problem when unit testing a production ready app to 90%+ coverage. I can only assume that not many teams unit test to a high standard.

Cheers!
Rob

Andrew Eisenberg wrote
Are you finding any differences when you run inside of STS vs when you
run on the command line.

On Fri, Feb 25, 2011 at 6:11 AM, cats <grails@rpc-soft.com> wrote:
>
> OK, I got round to looking at this again yesterday (somewhat inspired by the
> fact that our hudson build was failing due to OOM :-))
>
> It turns out that mockConfig() leaks like a sieve, and we were calling
> mockConfig() for a high percentage of our unit tests (we now have about
> 750). By default we were passing the Config.groovy file to this in setup
> like so:
>
>        @Override
>        protected void setUp() {
>                super.setUp();
>                mockConfig(new File( 'grails-app/conf/Config.groovy' ).text)
>        }
>
> Every time this was called it leaked a bit more until everything ground to a
> halt.
> It seems that ConfigSlurper is the culprit underneath mockConfig() method.
>
> In order to work around this I used a common superclass for unit tests in
> between us and GrailsUnitTestCase which does a one-time static cache of the
> ConfigObject. Once this is set, then our new mockConfig just reuses the
> cached ConfigObject rather than continually calling ConfigSlurper.
>
> During debugging this, I also noted that if you use mockConfig to mock some
> snippet of code, then we were getting weird problems with the subsequent
> integration tests, where we need to simulate a user logging in to spring
> security. I guess somewhere in the static caching inside the
> ConfigurationHolder it was remembering the crippled notion of what a config
> was, and then this was affecting the subsequent integration tests.
>
> Anyway, the single simple static cached ConfigObject seems to be the
> solution.
> Moral of the story: do not make many multiple calls to ConfigSlurper.parse()
> or mockConfig() !
>
> Yet again, Grails gives with one hand, and takes away with the other ...
>
> Cheers!
> Rob
> --
> View this message in context: http://grails.1312388.n4.nabble.com/STS-grails-junit-memory-leak-tp3262084p3324486.html
> Sent from the Grails - user mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

cats
In reply to this post by Andrew Eisenberg

No difference, the STS bit was a red herring. The OOM happened in our Hudson build as well as within STS. The problem is pure groovy ... ConfigSlurper leaks, which may not be such a problem, but the grails mocking framework advertises mockConfig as suitable for purpose, which it is not.

What surprises me is that I would have thought a lot more people would have hit this problem when unit testing a production ready app to 90%+ coverage. I can only assume that not many teams unit test to a high standard.

Cheers!
Rob

Andrew Eisenberg wrote
Are you finding any differences when you run inside of STS vs when you
run on the command line.

On Fri, Feb 25, 2011 at 6:11 AM, cats <grails@rpc-soft.com> wrote:
>
> OK, I got round to looking at this again yesterday (somewhat inspired by the
> fact that our hudson build was failing due to OOM :-))
>
> It turns out that mockConfig() leaks like a sieve, and we were calling
> mockConfig() for a high percentage of our unit tests (we now have about
> 750). By default we were passing the Config.groovy file to this in setup
> like so:
>
>        @Override
>        protected void setUp() {
>                super.setUp();
>                mockConfig(new File( 'grails-app/conf/Config.groovy' ).text)
>        }
>
> Every time this was called it leaked a bit more until everything ground to a
> halt.
> It seems that ConfigSlurper is the culprit underneath mockConfig() method.
>
> In order to work around this I used a common superclass for unit tests in
> between us and GrailsUnitTestCase which does a one-time static cache of the
> ConfigObject. Once this is set, then our new mockConfig just reuses the
> cached ConfigObject rather than continually calling ConfigSlurper.
>
> During debugging this, I also noted that if you use mockConfig to mock some
> snippet of code, then we were getting weird problems with the subsequent
> integration tests, where we need to simulate a user logging in to spring
> security. I guess somewhere in the static caching inside the
> ConfigurationHolder it was remembering the crippled notion of what a config
> was, and then this was affecting the subsequent integration tests.
>
> Anyway, the single simple static cached ConfigObject seems to be the
> solution.
> Moral of the story: do not make many multiple calls to ConfigSlurper.parse()
> or mockConfig() !
>
> Yet again, Grails gives with one hand, and takes away with the other ...
>
> Cheers!
> Rob
> --
> View this message in context: http://grails.1312388.n4.nabble.com/STS-grails-junit-memory-leak-tp3262084p3324486.html
> Sent from the Grails - user mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

Ian Roberts
In reply to this post by cats
On 25/02/2011 18:01, cats wrote:
>
> No difference, the STS bit was a red herring. The OOM happened in our Hudson
> build as well as within STS. The problem is pure groovy ... ConfigSlurper
> leaks, which may not be such a problem, but the grails mocking framework
> advertises mockConfig as suitable for purpose, which it is not.
>
> What surprises me is that I would have thought a lot more people would have
> hit this problem when unit testing a production ready app to 90%+ coverage.
> I can only assume that not many teams unit test to a high standard.

Or they don't use mockConfig - for my own unit tests I tend to just mock
the bits of the config that that particular test needs to use:

serviceUnderTest.grailsApplication = [config:new ConfigObject()]
serviceUnderTest.grailsApplication.config.x.y.z = "value"

mockConfig itself is remarkably simple:

ConfigurationHolder.config = new ConfigSlurper().parse(config)

I suspect that if you were to use the ConfigSlurper.parse method that
takes a Class rather than a String it would not leak permgen as it would
not be re-parsing the Config script every time.

ConfigurationHolder.config = new ConfigSlurper().parse(
  Class.forName("Config"))

Maybe there's a case for adding this variant of mockConfig to
GrailsUnitTestCase (or, thanks to Groovy dynamic dispatch, simply making
the config parameter to mockConfig untyped).

Ian

--
Ian Roberts               | Department of Computer Science
[hidden email]  | University of Sheffield, UK

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: STS grails junit memory leak

cats
Hi Ian,
I think you are right that you can work around a permgen leak, and I did play with this a little. The fact is that it is not permgen that is the problem - it is leaking into the real heap.

As you say, avoiding mockConfig by just setting the bit you want makes sense; I was being a bit provocative saying people are not testing properly, but we have spent quite a bit of time working around the mocking holes in grails! I will qualify that by saying our grails app has been a massive success for our users and with zero (well none that they have discovered) bugs!

Cheers!
Rob