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.