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 21:03:42 GMT
On 29 March 2017 at 20:54, Keith Suderman <suderman@anc.org> wrote:
> Two optimizations I have not seen mentioned so far; don't be so Groovy ;-)

:-) My background is Python, so I tend to think in terms of highly
dynamic code. That of course is why I like Groovy ;-)

> 1. Replace the the Map<> with an array of primitive ints. Why use an integer
> as a key into a hash map when it can be used as an array index?
> int[] results = new int[19] // since we need to index values 3..18

Two reasons, which I did mention, but only in in passing. I don't
necessarily know the range of outputs (so a fixed upper bound may not
be appropriate), and in some cases the result may not even be an int.
I could special-case those situations, but I'd prefer to get as much
out of a general design as I can before going down that route.

> 2. Replace the N.times{} or (1..N).each{} loops with a good old fashioned
> for(int i=0;i<N;i++) loop. I was actually surprised how much of an
> improvement this made if @CompileStatic was not used.  For statically
> compiled code this didn't really make a difference, but for dynamic code the
> speed up is huge.

I'll definitely try that!

The roll() function will ultimately (in my final version) be supplied
by the user, so I don't want to impose too many restrictions on what's
allowed there. I'm OK with making the user responsible for a certain
level of tuning the code, but a key goal for me is to make the way the
user specifies the function to simulate as straightforward as
possible.

> Of course, the big winner is using @CompileStatic, which when combined with
> using an array results in a  ~10x speed up.

Yep, those figures are impressive. I'll take a good look at
@CompileStatic - I've not really looked at it much yet. From what I've
read, it imposes some restrictions on the code, but I don't think the
restrictions will be a problem for my situation. One thought, though -
if the function being simulated is supplied by the user, would it have
to be the user's responsibility to include the @CompileStatic
annotation? I assume it's not possible for my simulation function to
take the user's code as input, and apply @CompileStatic to it before
running it? Even if I don't want a solution that reads code at
runtime, I'd still probably like a function that took the user's code
as a closure - something like "simulate(1000000) { user code here }"
but again I assume that means I can't use @CompileStatic?

The array definitely seems like a win, and as it's something I can do
in the driver code without affecting the user code, I may look again
at that. Maybe I'll try a hybrid approach that uses an array for most
values with a map to hold "outliers" (numbers bigger than I expect and
non-numbers). That may lose the benefit, though - the only way to know
for sure is to measure.

Thanks for the suggestions.
Paul

Mime
View raw message