[racket] Vast performance differences with minute syntactic differences

From: J. Ian Johnson (ianj at ccs.neu.edu)
Date: Thu Oct 4 19:01:54 EDT 2012

In many cases this is a "no duh" since speed-up loops can be inconspicuously small.
This post is regarding the macro writers' bill of rights, which I think Racket is violating.

I have two definitional interpreters that are run in an "abstract interpretation monad" if you will. One is syntactically generalized to allow for different interpretation strategies. In the case that the chosen strategy is the original one, they produce almost exactly the same code.

By almost exactly I mean
(let () (set-add res v))

versus

(let ([res res])
 (set-add (let ([v v]) 
             (set-add res (let () v)))))

cpu time: 5480 real time: 5584 gc time: 108
cpu time: 187492 real time: 187484 gc time: 1688

Code here:
https://gist.github.com/3836966

I've separated the commonalities into a module, where small non-recursive functions that are called in the main loop are turned into define-syntax-rules.

The main differences are in the macros in the tweaks module, and deref/get-val in the slow module. Diffing the fast/slow modules should show you very minor changes, yet the performance differences are huge.

Any insight anyone can share on this would be a great help.

Thanks,
-Ian

Posted on the users mailing list.