> - 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





Reply via email to