On 29 March 2017 at 20:54, Keith Suderman <suder...@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