groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alain Stalder <astal...@span.ch>
Subject Re: Improve Groovy class loading performance and memory management
Date Mon, 16 May 2016 15:01:43 GMT
My time here is running up, other things to attend to, so here is what
I wrote about the current state of class loading and garbage collection
in Groovy in the just updated user manual of Grengine:

https://www.grengine.ch/manual.html#the-cost-of-session-separation
--
==== The Cost of Session Separation

Although loading classes from bytecode obtained from compiling Groovy 
scripts
is a lot less expensive than compiling them (plus afterwards also 
loading the
resulting bytecode), it is still somewhat more expensive than one might 
naively
expect and there are a few things to be aware of when operating that way.

In the following, I will simply call classes compiled by the Groovy compiler
from Groovy scripts/sources _Groovy classes_ and classes compiled by the 
Java
compiler from Java sources _Java classes_.

* *Class Loading* +
   Experimentally, loading of a typical Groovy class is often about 10 times
   slower than loading a Java class with similarly complex source code, but
   both are relatively expensive operations (of the order of a millisecond
   for a small Groovy class, to give a rough indication). For Java classes,
   this is apparently mainly expensive because some security checks have to
   be made on the bytecode. For Groovy classes, it is mainly expensive
   because some meta information is needed to later efficiently call methods
   dynamically, and the like.
* *Garbage Collection* +
   Classes are stored in _PermGen_ (up to Java 7) resp. _Metaspace_ (Java 8
   and later) plus some associated data on the Heap, at least for Groovy
   classes the latter is normally the case (meta information). Whereas for
   Java classes, unused classes appear to be usually garbage collected from
   PermGen/Metaspace continuously, with Groovy classes this experimentally
   does not happen before PermGen/Metaspace or the Heap reach a configured
   limit. Why exactly this is so and whether it is easy to change and 
whether
   it will change in the future, is difficult to answer for me, I find the
   code around it is rather convoluted, hard to untangle. Note that by 
default
   on Java VMs there is typically no limit set for Metaspace (but there is
   for PermGen), so setting a limit is crucial in practice when using 
Groovy.
* *Garbage Collection Bugs* +
   In the past, several Groovy versions had failed at garbage collecting
   Groovy classes and their class loaders, resulting finally in an
   `OutOfMemoryError` due to exhaustion of PermGen/Metaspace or the Heap,
   whichever limit was reached first. If when you are reading this, Groovy
   2.4.6 is (still) the newest version, make sure you set the system 
property
   `groovy.use.classvalue=true` in the context of Grengine. Note that under
   different circumstances, like the one described in
   https://issues.apache.org/jira/browse/GROOVY-7591[GROOVY-7591:
   Use of ClassValue causes major memory leak] you would instead have had to
   set it to false! That Groovy bug is actually in turn due to a bug in
   Oracle/OpenJDK Java VMs regarding garbage collection under some
   circumstances, more precisely a bug in a new feature (`ClassValue`)
   introduced in order to make thing easier(!) for dynamic languages in the
   Java VM, see 
https://bugs.openjdk.java.net/browse/JDK-8136353[JDK-8136353].

So, if you want to use session separation with Greninge (or otherwise want
to load many Groovy classes repeately), first set a limit on 
PermGen/Metaspace,
then verify that classes can be garbage collected in an environment close to
production and that throughput under load would be sufficient (despite the
relatively slow class loading performance of Groovy (and Java) classes 
in the
Java VM) and then use it. And don't forget to repeat this at least when you
upgrade Groovy to a new version, but possibly also when you upgrade Java.

Or see the next section for an alternative...
--

PS: By the way, very funny how Jochen Theodorou "garbage collected" what I
wrote about PhantomReference to a "[...]"...

Good luck with Groovy garbage collection.

Alain

Mime
View raw message