These are chat archives for unisonweb/unison

25th
Sep 2017
Paul Chiusano
@pchiusano
Sep 25 2017 15:32
@refried it is telling me this function has a call in non-tail position...
      @annotation.tailrec
      def loop(x0: D, x0b: V, x1: D, x1b: V, r: R): D =
        try step(step, x0, x0b, x1, x1b, r)
        catch { case SelfTC => loop(r.x0, r.x0b, r.x1, r.x1b, r) }
Edmund Noble
@edmundnoble
Sep 25 2017 15:32
GADT matching and tailrec do not work together
Paul Chiusano
@pchiusano
Sep 25 2017 15:32
hi @edmundnoble :)
SelfTC is just a case object
case object SelfTC extends Throwable { override def fillInStackTrace = this }
Edmund Noble
@edmundnoble
Sep 25 2017 15:34
Ah.
Paul Chiusano
@pchiusano
Sep 25 2017 15:36
I feel like I have seen this work before with other exception types...
Edmund Noble
@edmundnoble
Sep 25 2017 15:55
That solution sounds massively more inefficient than using while :/
Paul Chiusano
@pchiusano
Sep 25 2017 15:55
eh, that is not going to be the same loop
better to just do while loop
Paul Chiusano
@pchiusano
Sep 25 2017 16:01
@refried pushed those benchmarks, made them closer to the real thing (with some more indirection), JIT was unimpressed and still optimized the hell out of it
@refried if you have time today, can you try running that same loop via the actual compiled Unison code, and if it is much slower than benchmark see if we are doing anything obviously dumb
Arya Irani
@aryairani
Sep 25 2017 18:58
Yeah
Arya Irani
@aryairani
Sep 25 2017 20:58
1.0             double-based loop
1.33            unison-based exception loop (1)
92.31           unison loop
@pchiusano
I think it could be faster if letrec detected that the only recursive calls are selfcalls, and skipped saving a lazy self reference. letrec1 used to do this, but the optimization shouldn't be limited to a letrec1 construction
or maybe there's something we can do to make those bindings not be indirect references after all
Arya Irani
@aryairani
Sep 25 2017 21:05
and i committed
Paul Chiusano
@pchiusano
Sep 25 2017 21:06
Oh so that is just testing loops that are dynamic tail calls to those delayed functions
Paul Chiusano
@pchiusano
Sep 25 2017 21:18
@refried ?
Arya Irani
@aryairani
Sep 25 2017 21:19
er... something like that, let me doublecheck
Paul Chiusano
@pchiusano
Sep 25 2017 21:20
If so am not surprised it is much slower, though I think we can improve that codepath also
Delay is bad - it has to force a thunk and then do a virtual call for each step through
Arya Irani
@aryairani
Sep 25 2017 21:23
no, i take it back, i don't really think that's happening here
I'm doing like
let rec 
  sum1toN n acc = if (n == 0) then acc else sum1toN (n - 1) (acc + n)
in sum1toN
and then passing the args to the result of that
so on second thought, I don't think it's hitting the Delay during the benchmark
Arya Irani
@aryairani
Sep 25 2017 21:32
i.e. the delays happen when evaluating the body of the letrec, but I do that before I start the benchmark, and I just time the evaluated body; if anything it should be unfair in our favor
Paul Chiusano
@pchiusano
Sep 25 2017 21:34
Hmm I was thinking there will be a force of a delay on every recursive call, since the recursive var ref will be wrapped in a delay
@refried
Arya Irani
@aryairani
Sep 25 2017 21:35
but it's a selfcall so recursive var ref isn't used anyway
Paul Chiusano
@pchiusano
Sep 25 2017 21:36
Oh maybe... I gotta run
Let's touch base tomorrow
Arya Irani
@aryairani
Sep 25 2017 21:36
co-recursive calls would have the indirection i think. ttyl
Arya Irani
@aryairani
Sep 25 2017 22:47
I ran it through a profiler and to me it looks like half of the time is spent in step, and half of the time is spent filling the Result registers and/or throwing the exception