On 07/06/2013, at 5:52 PM, Szczepan Faber <szczepan.fa...@gradleware.com> wrote:
> >@Szczepan, this would be a good candidate to add to your list: reusing > >warmed up user classes (which includes scripts and plugins) should give a > >nice performance improvement to build time, and configuration time in > >particular, with the daemon > > Is there a chance it also tangibly reduces the heap consumption? Absolutely. This is why I think it might be a good option for you to look at. > How big this story is? It should be relatively quick to spike, to see if it's worthwhile. Implementation is another story. I think the bulk of the work would be detangling some of the file snapshot and change detection stuff from task up-to-date checking so that we can reuse it for classpath up-to-date checking. > Say that I'm interested in a tangible performance improvement (+ perhaps > heap), without yet solving those other interesting use cases. We wouldn't need to solve the other use cases. > > Cheers! > > > On Fri, Jun 7, 2013 at 1:19 AM, Adam Murdoch <adam.murd...@gradleware.com> > wrote: > > On 05/06/2013, at 3:38 PM, Luke Daley <luke.da...@gradle.biz> wrote: > >> >> >> On 05/06/2013, at 2:37, Adam Murdoch <adam.murd...@gradleware.com> wrote: >> >>> >>> On 05/06/2013, at 3:57 AM, Luke Daley <luke.da...@gradleware.com> wrote: >>> >>>> Hi, >>>> >>>> I just tracked down a memory leak in the Artifactory plugin. I've raised >>>> with them to fix this, but this is a symptom of a more general leak we >>>> have in placeā¦ I think. >>>> >>>> Groovy keeps a global registry of metaclass of all loaded classes that get >>>> touched by Groovy. We load Groovy in a persistent classloader across >>>> builds. This means that build level user classes (e.g. non core plugins) >>>> end up getting loaded into Groovy's metaclass registry each time there is >>>> a build. This means we are always leaking permgen, and that we are very >>>> susceptible to bad leaks if user code keeps a static state reference to >>>> something, as was the case with the artifactory plugin. They ended up >>>> holding on to a reference of the root project statically (through Groovy >>>> meta programming) which means a lot was leaked. >>>> >>>> We can't really change the classloader structure to unload the whole meta >>>> class registry between builds as that would defeat the main purpose of the >>>> daemon: to load Groovy once. >>> >>> The purpose of the daemon is to keep the things that a build needs >>> warmed-up. This includes groovy, but it also includes the user classes used >>> by the build (and other state, too). So, we only want to discard the >>> classes and associated meta-data that we think are unlikely to be needed >>> any more - classes from class loaders that we discard because their >>> classpath has changed or class loaders that we discard because we haven't >>> run the associated build for a while. >> >> My read of things was that we don't cache any user code at the moment. The >> growing meta class registry seems to indicate that we are dumping user >> classes between builds. > > I got confused. We aren't reusing anything. For some reason I thought we had > implemented this. This would be a good place to start as far as fixing the > leak goes. > > @Szczepan, this would be a good candidate to add to your list: reusing warmed > up user classes (which includes scripts and plugins) should give a nice > performance improvement to build time, and configuration time in particular, > with the daemon. With the daemon, we see roughly a 20% improvement in > execution time between the 2nd and 5th (or so) build invocations as the > hotspot compiler does its thing. This is beyond the initial improvement > between the 1st and 2nd invocations. I'd expect to see something similar for > user code. > > It also reduces the chance of memory leaks. It eliminates some types of > problems and adds some others, but I think on the balance it should be better. > > Reusing the user classes means we'd need to track changes to classpaths > efficiently, and this means we can do some interesting things on change: > - invalidate a task's outputs when the task implementation changes > - notify the tooling API client that the model may have changed. > > And we can cache some interesting information derived from a classpath: > - the API for the classpath, which can be used for up-to-date checks > and compilation. > - plugin meta-data scanned from the classpath (eg > @Plugin(id='my-plugin') annotation, or plugin supplied services). > - test detection. > - the project model, or enough of the model to decide it the project's > outputs are up-to-date or not. > > > -- > Adam Murdoch > Gradle Co-founder > http://www.gradle.org > VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting > http://www.gradleware.com > > Join us at the Gradle Summit 2013, June 13th and 14th in Santa Clara, CA: > http://www.gradlesummit.com > > > > > -- > Szczepan Faber > Principal engineer@gradleware; Lead@mockito > Join me at the Gradle Summit 2013, June 13th and 14th in Santa Clara, CA: > http://www.gradlesummit.com -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com Join us at the Gradle Summit 2013, June 13th and 14th in Santa Clara, CA: http://www.gradlesummit.com