On Jan 16, 5:15 am, Christian Vest Hansen <karmazi...@gmail.com>
wrote:
> Here's my theory.
>
> In your when example, "when" is a macro that is expanded to an "if"
> special form. Your other examples, however, wrap your code in a
> function call.
>
> Now, functions in Clojure can't really take primitive arguments, so in
> spite of your coercion efforts Clojure introduces boxing in your loop
> and this is what slows you down.
>
> A work-around is to either use a (def variable ...) or something like this:
>
> (let [x (time (loop [i (int 0)] (if (< i (int 30000000)) (recur (inc
> i)) i)))] (prn x))
>
> How does that sound?
>
>
>
> On Fri, Jan 16, 2009 at 5:43 AM, Jason Wolfe <jawo...@berkeley.edu> wrote:
>
> > I was doing some microbenchmarking earlier, and I noticed some very
> > very weird anomalies.   If anyone could shed some light on what's
> > going on that would be awesome. (I'm using the latest SVN, and have
> > verified this on a totally clean repl).
>
> > Simplified as much as possible, the heart of what I observed is:
>
> > user> (prn (time (loop [i (int 0)] (if (< i (int 30000000)) (recur
> > (inc i)) i))))
> > "Elapsed time: 4247.477 msecs"
> > 30000000
> > nil
>
> > user> (time (loop [i (int 0)] (if (< i (int 30000000)) (recur (inc i))
> > i)))
> > "Elapsed time: 128.37 msecs"
> > 30000000
>
> > Weird, right?  The prn is *outside* the loop, and yet it still affects
> > the timing somehow.  Maybe this is something specific to printing?
> > Nope:
>
> > user> (first (time (loop [i (int 0)] (if (< i (int 30000000)) (recur
> > (inc i)) [i]))))
> > "Elapsed time: 4264.847 msecs"
> > 30000000
>
> > user> (time (loop [i (int 0)] (if (< i (int 30000000)) (recur (inc i))
> > [i])))
> > "Elapsed time: 130.099 msecs"
> > [30000000]
>
> > But, some other expressions around the "time" don't affect it in the
> > same way:
>
> > user> (when (time (loop [i (int 0)] (if (< i (int 30000000)) (recur
> > (inc i)) [i]))) 12)
> > "Elapsed time: 130.236 msecs"
> > 12
>
> > In case you were wondering, this has nothing to do with the "time"
> > macro.
>
> > user> (first (loop [i (int 0)] (if (< i (int 30000000)) (recur (inc
> > i)) [i])))
> > ; ...  4 seconds pass on my stopwatch ...
> > 30000000
>
> > And the slowness is by a multiplicative, not additive factor:
>
> > user> (first (time (loop [i (int 0)] (if (< i (int 60000000)) (recur
> > (inc i)) [i]))))
> > "Elapsed time: 8576.649 msecs"
> > 60000000
>
> > user> (time (loop [i (int 0)] (if (< i (int 60000000)) (recur (inc i))
> > [i])))
> > "Elapsed time: 250.407 msecs"
> > [60000000]
>
> > I'm at a total loss for what's going on.  Anyway, I'll stop here for
> > now in case I'm missing something stupid or obvious.
>
> > Thanks for your help!
> > Jason
>

The bytecode produced for the loop is exactly the same in both cases.
It seems the presence of first (or really anything) on the stack
during looping causes HotSpot to bail on optimizing. This is a case
where the bytecode is unlike any produced by javac (in Java, loops
cannot be expressions).

For now, I've made it so that when a loop occurs as an expression it
is lifted out into a fn, and the performance is identical.

SVN 1216 - thanks for the report.

Rich

--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to