You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Alain Stalder <as...@span.ch> on 2015/09/01 09:18:38 UTC

Re: [ANN] Grengine 1.0.4

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






Re: [ANN] Grengine 1.0.4

Posted by Jochen Theodorou <bl...@gmx.org>.
Am 01.09.2015 09:18, schrieb Alain Stalder:
[...]
> 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.

I think your scenario is different. You unload/load classes, yes, but 
the Groovy runtime stays. The problem there was about the runtime not 
unloading. Classes of child loaders to the loader of the runtime can 
still be unloaded in most cases.

[...]
> 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.

If you would not have to verify the classes it could be done much 
faster. As for garbage collection, below JDK9 using concurrent mark and 
sweep collector you can enable class unloading and it can happen more 
often.


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

depends on what you compare with. Sure... if you for example think about 
templates and a webserver using the template to produce the pages, you 
need something fast. And a String based solution for example can here be 
pretty fast. But if the page is called often, a class based solution can 
become faster again. So you start optimizing for your cases. Same for 
the JVM

bye blackdrag

-- 
Jochen "blackdrag" Theodorou
blog: http://blackdragsview.blogspot.com/


Re: [ANN] Grengine 1.0.4

Posted by Pascal Schumacher <pa...@gmx.net>.
Am 03.09.2015 um 08:41 schrieb Alain Stalder:
> > [...]
> > > 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.
> >
> > If you would not have to verify the classes it could be done much
> > faster.
>
> Ah, I see. Probably no sensible way around that for security reasons...
Well you could use "-noverify", but as you said it's not recommended for 
security reasons:

https://blogs.oracle.com/buck/entry/never_disable_bytecode_verification_in


Re: Re: [ANN] Grengine 1.0.4

Posted by Alain Stalder <as...@span.ch>.
Jochen "blackdrag" Theodorou wrote:
 > Am 01.09.2015 09:18, schrieb Alain Stalder:
 > [...]
 > > 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.
 >
 > I think your scenario is different. You unload/load classes, yes, but
 > the Groovy runtime stays. The problem there was about the runtime not
 > unloading. Classes of child loaders to the loader of the runtime can
 > still be unloaded in most cases.

OK. :)

 > [...]
 > > 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.
 >
 > If you would not have to verify the classes it could be done much
 > faster.

Ah, I see. Probably no sensible way around that for security reasons...

 > > As for garbage collection, below JDK9 using concurrent mark and
 > > sweep collector you can enable class unloading and it can happen more
 > > often.

OK, would explain what I observed with JDK 9. To me this is already an
important improvement.

 > > Pretty bad for a dynamic language like Groovy that always compiles to
 > > classes in the JVM... :(
 >
 > depends on what you compare with. Sure... if you for example think about
 > templates and a webserver using the template to produce the pages, you
 > need something fast. And a String based solution for example can here be
 > pretty fast. But if the page is called often, a class based solution can
 > become faster again. So you start optimizing for your cases. Same for
 > the JVM

Makes sense, I agree.

Best wishes,
Alain

Re: [ANN] Grengine 1.0.4

Posted by Alain Stalder <as...@span.ch>.
I wrote:
 > Or is there maybe at least hope on the horizon for Java 9 or 10 ?

Appears to be, at least as far as garbage collection of class loaders 
and their classes is concerned. Yesterday a current preview of JDK 9 
behaved much better with regards to collecting class loaders and their 
classes. First the number of classes was rising as I created class 
loaders and used them to load a class in a loop (and then kept no 
references), but after rising a bit, occupied MetaSpace became a 
straight line, as class loaders and their classes were continuously 
garbage collected from then on...

Maybe this can also be achieved with Java 8 and earlier by tweaking JVM 
parameters, but to me JDK 9 seems to be the first JVM where this works 
"out-of-the-box", which is crucial for many applications, I would say.