(no subject)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

(no subject)

Thibault Kruse
Hi,

(I tried sending this mail before, failed so far)

This is about using @CompileStatic inside core Groovy code.

The analysis of gradle plugins by Cedric revealed a potential
problem with dynamic Groovy:

http://melix.github.io/blog/2016/05/gradle-kotlin.html
"I think at some point, someone made a terrible design decision in
Groovy. I don’t know who it was, but the idea was to rely on
exceptions to control the flow of resolution of properties. This means
that when a property is missing, typically in a closure, an exception
is thrown. When a method is not found, an exception is thrown. When a
property is not found, an exception is thrown. That seemed to be a
good idea, because in the end, you want to provide the user with an
error, but in practice, this is catastrophic, because Groovy can
capture those exceptions. Typically, in a delegation chain (nested
closures), a containing closure or class can actually have this
property defined, or implement property missing/method missing. Now,
re-think a second about the "simple" example of Gradle build above:
how do you now where to look up for message, top, signature, …? Now
you know: f* exceptions are thrown, stack traces are filled, and
eventually captured because some composite dynamic object finally
wants to answer the message… In practice, for some builds I have
profiled, it was tens of thousands of exceptions being thrown and
stack traces filled for nothing. And that has a terrible impact on
performance."

Now I am wondering, since parts of Groovy itself are written in
Groovy, and @CompileStatic is not much used in side Groovy itself,
does core Groovy suffer from performance issues due to the same reasons
as well?
Reply | Threaded
Open this post in threaded view
|

Re:

Alessio Stalla
I'm not really answering your question, but, AFAIK, Groovy is not the only JVM language to use exceptions for control flow. Maybe it is using too many of them, too often, I don't know. Anyway, not filling the stack trace can help a lot with exception performance, so that may be a cheap solution.

On 5 July 2016 at 10:05, Thibault Kruse <[hidden email]> wrote:
Hi,

(I tried sending this mail before, failed so far)

This is about using @CompileStatic inside core Groovy code.

The analysis of gradle plugins by Cedric revealed a potential
problem with dynamic Groovy:

http://melix.github.io/blog/2016/05/gradle-kotlin.html
"I think at some point, someone made a terrible design decision in
Groovy. I don’t know who it was, but the idea was to rely on
exceptions to control the flow of resolution of properties. This means
that when a property is missing, typically in a closure, an exception
is thrown. When a method is not found, an exception is thrown. When a
property is not found, an exception is thrown. That seemed to be a
good idea, because in the end, you want to provide the user with an
error, but in practice, this is catastrophic, because Groovy can
capture those exceptions. Typically, in a delegation chain (nested
closures), a containing closure or class can actually have this
property defined, or implement property missing/method missing. Now,
re-think a second about the "simple" example of Gradle build above:
how do you now where to look up for message, top, signature, …? Now
you know: f* exceptions are thrown, stack traces are filled, and
eventually captured because some composite dynamic object finally
wants to answer the message… In practice, for some builds I have
profiled, it was tens of thousands of exceptions being thrown and
stack traces filled for nothing. And that has a terrible impact on
performance."

Now I am wondering, since parts of Groovy itself are written in
Groovy, and @CompileStatic is not much used in side Groovy itself,
does core Groovy suffer from performance issues due to the same reasons
as well?

Reply | Threaded
Open this post in threaded view
|

Re:

Jochen Theodorou
In reply to this post by Thibault Kruse


On 05.07.2016 10:05, Thibault Kruse wrote:
> Hi,
>
> (I tried sending this mail before, failed so far)
>
> This is about using @CompileStatic inside core Groovy code.
>
> The analysis of gradle plugins by Cedric revealed a potential
> problem with dynamic Groovy:

It is no new problem, it is, as Cedric said, a "terrible design
decision"... done somewhen long ago... 10+ years ago. Back then it made
more sense, because back then the MetaClass was always doing the actual
invocation. With callsite caching this changed.... but the time back
then was not used to correct that mistake.

[...]
> Now I am wondering, since parts of Groovy itself are written in
> Groovy, and @CompileStatic is not much used in side Groovy itself,
> does core Groovy suffer from performance issues due to the same reasons
> as well?

that is not easy to answer... the compiler is in Java, but transforms
might be in Groovy, so there is potential, even though it is not much.
Then the runtime core is in Java, but we are doing dynamic invocations
inside, from Java code at some points.

No, in total I must say it depends on your use case. We have some paths,
that may suffer from that and many paths that do not. if you for example
test against a builder, then you would of course get the problem. Method
invocations for example do not have the problem as much... properties
tend to have problems, but if you want to write a benchmark, you cannot
use a local variable or field in the same class. You have to access the
property of something that is not "this". And then you should notice
terrible performance, because afaik we do not cache property access at
all in non-indy.

bye Jochen
Reply | Threaded
Open this post in threaded view
|

Re:

Remi Forax
Just a note,
Java has exactly the same bug when loading a class (at least Java before 9), when a class is not found, the classloader throw a ClassNotFoundException which may be catched by another classloader down the stack.

The JIT (c2) even try to optimize such case by avoiding to fill the stack trace and transforming the throw/catch to a goto, but usually, the chain of callers is to deep to be optimized correctly :(

Rémi

----- Mail original -----

> De: "Jochen Theodorou" <[hidden email]>
> À: [hidden email]
> Envoyé: Mardi 5 Juillet 2016 13:52:18
> Objet: Re:
>
>
>
> On 05.07.2016 10:05, Thibault Kruse wrote:
> > Hi,
> >
> > (I tried sending this mail before, failed so far)
> >
> > This is about using @CompileStatic inside core Groovy code.
> >
> > The analysis of gradle plugins by Cedric revealed a potential
> > problem with dynamic Groovy:
>
> It is no new problem, it is, as Cedric said, a "terrible design
> decision"... done somewhen long ago... 10+ years ago. Back then it made
> more sense, because back then the MetaClass was always doing the actual
> invocation. With callsite caching this changed.... but the time back
> then was not used to correct that mistake.
>
> [...]
> > Now I am wondering, since parts of Groovy itself are written in
> > Groovy, and @CompileStatic is not much used in side Groovy itself,
> > does core Groovy suffer from performance issues due to the same reasons
> > as well?
>
> that is not easy to answer... the compiler is in Java, but transforms
> might be in Groovy, so there is potential, even though it is not much.
> Then the runtime core is in Java, but we are doing dynamic invocations
> inside, from Java code at some points.
>
> No, in total I must say it depends on your use case. We have some paths,
> that may suffer from that and many paths that do not. if you for example
> test against a builder, then you would of course get the problem. Method
> invocations for example do not have the problem as much... properties
> tend to have problems, but if you want to write a benchmark, you cannot
> use a local variable or field in the same class. You have to access the
> property of something that is not "this". And then you should notice
> terrible performance, because afaik we do not cache property access at
> all in non-indy.
>
> bye Jochen
>
Reply | Threaded
Open this post in threaded view
|

Re:

Cédric Champeau


2016-07-05 15:03 GMT+02:00 Remi Forax <[hidden email]>:
Just a note,
Java has exactly the same bug when loading a class (at least Java before 9), when a class is not found, the classloader throw a ClassNotFoundException which may be catched by another classloader down the stack.

The JIT (c2) even try to optimize such case by avoiding to fill the stack trace and transforming the throw/catch to a goto, but usually, the chain of callers is to deep to be optimized correctly :(

In Gradle we try to workaround this with a `CachingClassLoader` that caches misses. But it cannot cover all cases, and yes, this is a terrible idea too, responsible for a lot of the classloading slowness in Gradle. 
Rémi

----- Mail original -----
> De: "Jochen Theodorou" <[hidden email]>
> À: [hidden email]
> Envoyé: Mardi 5 Juillet 2016 13:52:18
> Objet: Re:
>
>
>
> On <a href="tel:05.07.2016%2010" value="+33507201610">05.07.2016 10:05, Thibault Kruse wrote:
> > Hi,
> >
> > (I tried sending this mail before, failed so far)
> >
> > This is about using @CompileStatic inside core Groovy code.
> >
> > The analysis of gradle plugins by Cedric revealed a potential
> > problem with dynamic Groovy:
>
> It is no new problem, it is, as Cedric said, a "terrible design
> decision"... done somewhen long ago... 10+ years ago. Back then it made
> more sense, because back then the MetaClass was always doing the actual
> invocation. With callsite caching this changed.... but the time back
> then was not used to correct that mistake.
>
> [...]
> > Now I am wondering, since parts of Groovy itself are written in
> > Groovy, and @CompileStatic is not much used in side Groovy itself,
> > does core Groovy suffer from performance issues due to the same reasons
> > as well?
>
> that is not easy to answer... the compiler is in Java, but transforms
> might be in Groovy, so there is potential, even though it is not much.
> Then the runtime core is in Java, but we are doing dynamic invocations
> inside, from Java code at some points.
>
> No, in total I must say it depends on your use case. We have some paths,
> that may suffer from that and many paths that do not. if you for example
> test against a builder, then you would of course get the problem. Method
> invocations for example do not have the problem as much... properties
> tend to have problems, but if you want to write a benchmark, you cannot
> use a local variable or field in the same class. You have to access the
> property of something that is not "this". And then you should notice
> terrible performance, because afaik we do not cache property access at
> all in non-indy.
>
> bye Jochen
>