At Fri, 31 Jul 2015 18:56:15 +0100, Laurent wrote: > On Fri, Jul 31, 2015 at 5:40 PM, Matthew Flatt <mfl...@cs.utah.edu> wrote: > > > At Fri, 31 Jul 2015 15:03:53 +0100, Laurent wrote: > > > I don't really understand why `in-range` makes such a difference. It > > looks > > > like the kind of sequence iterator is tested at each step, whereas I was > > > expecting it to be tested only at the beginning of the loop, since this > > > sequence iterator kind can't change from one iteration to the next, > > right? > > > > > > Hence, I was expecting the `in-range` (and actually all other `in-*`) > > issue > > > to appear only inside nested loops, where some loops are started many > > times > > > (thus requiring many iterator kind tests). > > > > Right: The `in-*` functions tell `for` what kind of step operations to > > inline into the loop (after an initial guard that confirms that it has > > a number, list, etc., to iterate through). Otherwise, there's a > > run-time dispatch to take each step, which is usually more significant > > than a run-time dispatch to set up the loop. > > > > Apparently the optimizer is looking very specifically for `in-range`. This: > > (define my-in-range in-range) > (time (for ([x (my-in-range 40000000)]) > (+ x 3))) > > is as slow as not using `in-range` at all, which I find rather strange.
It's really the `for` macro that recognizes `in-*`. The expansion of a `for` form is too complex for the optimizer to see through the levels of dispatching. Giving macros more power to interact with the optimizer is a long-term goal, but it's beyond the things that Racket macros can do right now. > By "run-time dispatch", do you mean that the check of which kind the > argument is is done at each iteration? No... > Isn't it possible to test this only on the very first iteration? Then the > rest of the loop should be as fast as with `in-range`. The fact that `add1` should be used for stepping is determined once at the start of the loop. Since that determination is dynamic, however, the call to `add1` is not static in the bytecode, and so the JIT doesn't inline `add1`. Some JITs would detect that `add1` turns out to be the stepping function on the first iteration, when the loop is compiled. Then, the JIT would optimistically generate a faster path for future iterations where `add1` turns out to be the stepping function. It's possible that Racket's JIT could do that and achieve some intermediate performance --- not as fast as `in-range` but better than current performance without `in-range`. I'll have to try some experiments. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.