groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul Moore <p.f.mo...@gmail.com>
Subject Re: Optimising a Groovy script
Date Wed, 29 Mar 2017 14:34:38 GMT
On 29 March 2017 at 14:56, Nelson, Erick <Erick.Nelson@hdsupply.com> wrote:
> I'm not sure using or not using def would cause performance differences.

There definitely *seems* to be a difference.

def rng = new MersenneTwister()

def roll = {
    rng.nextInt(6) + rng.nextInt(6) + rng.nextInt(6) + 3
}

Both def: 0.4 to 0.5 sec
No def on rng, def on roll: 0.5 to 0.8 sec - spread seems greater, too
Def on rng, not on roll: 1.2 to 1.6 sec, with a couple of 1.9s.
Def on neither: 1.4 to 1.9 sec.

int roll() and no def on rng looks similar to def on roll and not on
rng. But def on rng isn't allowed when I'm using int roll().

All results from multiple runs on my PC, summarising the average/spread by eye.

So the big difference is removing def from roll, with removing def
from rng having a smaller but detectable effect.

> It just affects variable scope.
>
> http://mrhaki.blogspot.com/2009/11/groovy-goodness-variable-scope-in.html

I still find this confusing. That article says that def or type are
equivalent (in terms of scope). But int roll() doesn't allow def rng,
whereas def roll does.

I assume that the issue here is that

    def roll = { ... }

is making roll an attribute whose value is a closure. Whereas

    int roll() { ... }

is making roll a method? So that implies that you can't reference a
def from within a method, but you can reference it from within a
closure? OK, as a rule I can accept that might be the case, but I
don't understand why. Furthermore, I can't even refer to rng as
"this.rng" from within roll, which is very confusing, as I thought a
script was compiled as an implicit class, in which case isn't this the
instance of that class, and hence this.attr should be a means of
accessing any attribute of the class?

Looking at the details in the manual ("Program Structure" section 3
"Scripts vs Classes") I think I start to understand:

* def roll = { } is declaring a local variable in the implied run()
method, whose value is a closure
* roll = { } declares a variable in the "script binding" whose value
is a closure
* int roll { } is a method of the script class
* def rng = ... is a local variable of the run method, which the docs
explicitly state is not available to methods
* rng = ... is a variable in the script binding which *is* visible from methods
* @Field rng = ...is a field, which is what I'd need to use for
this.rng to work as I'm expecting

I'll have to look some more into the script binding. I don't really
understand the visibility rules for values in the binding, apart from
the few cases explicitly noted (e.g. "they are available from
methods").

Wow, this is more complicated than it looks at first glance!!!

On the other hand, fields, methods, closures and script bindings are
all very different things, so I can easily imagine them having
different performance characteristics. In don't know how I'd develop
an intuition about which is the right one to use in any specific
situation, though. Try them all and see which works better feels like
the only practical option at the moment :-(

Thanks,
Paul

Mime
View raw message