First of all, great post and a lot of great points.

I feel your pain, because I also find myself struggling a lot to make 
idiomatic code fast in Clojure. Often I end up being forced to use some 
pretty ugly tricks to get the performance I need. Sometimes I just end up 
coding inner loops in Java - this often ends up easier to maintain than a 
big pile of loop/recurs, macro magic, type hints and/or obscure casting 
tricks which is what you typically need to get the maximum performance in 
Clojure.

I definitely think there is scope for some extra optimisation techniques. 
It's a big and complex topic though, and requires people to get down and 
dirty with the compiler. I think the big wins would be things like:
a) More type checking/inference (to eliminate the need for type hints and 
casts in many circumstances)
b) Targeted optimisations for common functional patterns 
c) Smarter inlining of small functions
d) Ability to produce type-specialised versions of functions

Some of this could, I think, be implemented in an optimisation phase that 
performs macro-like transformations. I think this would be similar to the 
"abstraction layer" that you describe.

On Tuesday, 9 July 2013 16:11:58 UTC+1, Alexander Gunnarson wrote:
>
> Hello everyone! It's great to be here with all you fellow Clojurians. Just 
> so you know, this is my first post on this group, so don't shoot me if it's 
> terrible ;) 
>
> As background, I've been working through SICP and have been loving Scheme. 
> It's almost breathtaking how elegant and clean the code can be (I had some 
> moments 
> like xkcd goes off abou <http://xkcd.com/224/>t). Of course, though 
> Scheme is beautiful and simple, everyone knows that it's not especially 
> practical, in general. I love the Lisp paradigms but I'm not really a fan 
> of CL so I did some looking around and stumbled upon Clojure. It seems that 
> Clojure really has a lot going for it between shockingly easy concurrency 
> support and Java interop, among other things. But one thing that's been 
> bothering me is that it seems like to optimize performance in Clojure, you 
> have to sacrifice some elegance.
>
> *Example 1: Tail-call recursion*
>
> *Scheme*
> One example would be tail-call recursion. For instance, normally in Scheme 
> I'd naively implement an iterative exponent function like this:
>
> (define (expt x n)
>
>         (cond ((= 0 n) 1)
>
>               ((= 1 n) x)
>
>               (else (expt (* x x) (- n 1)))))
>
> Pure. Simple. Beautiful. (Not that I'm the best Scheme programmer ever, 
> but to me it looks beautiful, and it conforms well to the base of the 
> problem. You get the point.)
>
> *Clojure*
> Of course, tail-call recursion is not possible with JVM, so Clojure uses a 
> *recur* macro in place of direct recursive function calling. It avoids 
> blowing the stack as quickly but it's still not 100% "mathematically pure" 
> in the way Scheme tends to be.
>
> An added gripe is that the* else *form within *cond *in Clojure uses a 
> keyword, *:else*, instead of the more consistent parenthetical form used 
> in Scheme. I suppose that's to make it less "Lispy." But it just ends up 
> making it a little less elegant.
>
> *Example 2: Type casting*
> *
> *
> Some have said that Clojure can be somewhat slow (as with all Lisps). I'm 
> not sure how true this is, but I stumbled on an example on John Lawrence 
> Aspden's 
> blog<http://www.learningclojure.com/2013/02/clojure-is-fast-is-clojure-still-fast.html>.
>  
> He wrote a program to implement Euler's method like so:
>
> *First Solution*
>
> (defn f [t y] (- t y))
>
> (defn solveit [t0 y0 h its]
>   (if (> its 0) 
>     (let [t1 (+ t0 h)
>           y1 (+ y0 (* h (f t0 y0)))]
>       (recur t1 y1 h (dec its)))
>     [t0 y0 h its]))
>
>
> He points out that "if this was an assembly language program that worked the 
> way you'd expect, each loop would take 7 cycles." So he tests it for Clojure. 
> The result? On his netbook with Clojure 1.4: 2400 cycles. As he says, "We're 
> looking at a slowdown of about 300 times over what we could probably achieve 
> coding in assembler or in C with a good optimizing compiler." That's not 
> surprising, I suppose, but it's still a little disheartening. After all, you 
> want your language to be fast, right? Well, after a few iterations, he 
> manages to reduce the cycles way down - all the way down, in fact, to 37, 
> which is quite a feat. Like so:
>
>
> *Final Solution*
>
> (defn solveit-4 [t0 y0 h its]
>   (let [zero (long 0)]
>     (loop [t0 (double t0) y0 (double y0) h (double h) its (long its)]
>       (if (> its zero) 
>         (let [t1 (+ t0 h)
>               y1 (+ y0 (* h (- t0 y0)))]
>           (recur t1 y1 h (dec its)))
>       [t0 y0 h its]))))
>
>
> But the thing is, between the *recur *macro, explicit typecasting, and the 
> *loop* construct, yes, you have a very significant performance increase, but 
> it the code's gotten bigger, much less readable, and much less elegant.
>
>
> *The bottom line*
>
> *
> *
>
> My idea, which is probably very naive, but one which I'm curious about, is:
>
> *Is it possible to have some sort of set of automatic-optimizing macros that 
> work on Clojure code to preserve elegance while maximizing performance?*
>
> *
> *
>
> In theory, it would be kind of an abstraction layer. There would be one file 
> that would store the code that gets read and another output file that stores 
> the code that actually gets evaluated by the REPL, and a set of macros to 
> optimize the "front-end", "abstracted" file into the output, "nuts-and-bolts" 
> file to be evaluated by the REPL. Probably this would be a very intensive 
> process - I don't know. But maybe it's worth the trouble after all to save a 
> ton of programmer-hours by increasing readability.
>
>
> Thoughts?
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to