groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alain Stalder <astal...@span.ch>
Subject Re: [ANN] Grengine 1.0.4
Date Tue, 01 Sep 2015 07:18:38 GMT
 > - New (documentation): Section about the cost of session separation.
 > See: http://grengine.ch/manual.html#the-cost-of-session-separation

I have updated that section (you may have to reload the page).

In a nutshell, I was not aware (enough) of three things:

(this is about loading the "same class" several times, i.e. loading the 
same compiled bytecode from different parallel class loaders, in order 
to separate Groovy scripts as fully as possible, including their static 
member fields)

- The JVM does essentially not garbage collect class loaders and their 
classes once they are not used any more unless PermGen space resp. 
MetaSpace for Java 8 becomes sparse, which is especially bad with Java 8 
as per default there is practically no limit on MetaSpace size.
- Loading a class from bytecode is somewhat more expensive in terms of 
using processor time than I expected (meta information).
- Creating a Groovy MetaClass instance for each instantiated Groovy 
class is also quite expensive.

I guess in the end I am lucky it never got quite as hairy as for Cedric 
Champeau this week at Gradle Inc.:

http://melix.github.io/blog/2015/08/permgenleak.html

I saw no difference with Groovy 2.4.4 compared to 2.2.2 or 2.1.9, in my 
cases garbage collection worked once PermGen space resp. MetaSpace 
became sparse, class loaders and their classes were then collected, both 
with Oracle/Sun JDK 6 and 8.

Anyway, as a workaround instead of separating static fields by separate 
class loaders, it may under some circumstances be viable to prohibit 
static (non-final) fields or even just to warn, with a compilation 
customizer:

class NoStaticCompilationCustomizer extends CompilationCustomizer {
   NoStaticCompilationCustomizer() { super(CompilePhase.CANONICALIZATION) }
   void call(SourceUnit source, GeneratorContext context, ClassNode 
classNode)
       throws CompilationFailedException {
     classNode.fields.each { field ->
       if (Modifier.isStatic(field.modifiers) && 
!Modifier.isFinal(field.modifiers)) {
         // throw or warn, etc.
       }
     }
   }
}
...
def config = new CompilerConfiguration()
config.addCompilationCustomizers(new NoStaticCompilationCustomizer())


Overall a bit disappointing that at the age of about 20, the JVM is not 
able to handle dynamic class loading and especially garbage collection 
of class loaders and loaded classes efficiently, i.e. automatically and 
with relatively little performance overhead.

Pretty bad for a dynamic language like Groovy that always compiles to 
classes in the JVM... :(

    Or am I missing something essential?

Or is there maybe at least hope on the horizon for Java 9 or 10 ?

Alain






Mime
View raw message