Using `def` like that is simply incorrect. `def` should always be at the
top level unlike say Scheme.

I would first remove all internal defs and then rerun your benchmarks.


On Fri, Jun 21, 2013 at 8:36 AM, Colin Yates <colin.ya...@gmail.com> wrote:

> Hi all,
>
> I am doing some (naive and trivial) performance tests before deciding
> whether and how to use Clojure for some performance critical number
> cruching and I wanted help understanding the behaviour.
>
> I am defining an array inside a function, setting the contents to be 1 and
> then summing them up (by areducing) them (I chose 1 instead of a random
> number for consistency, obviously the contents will be different otherwise
> it would all reduce to (n) :)).  If I 'let' the array then it is factors of
> 10 faster than if I def the array.
>
> The relevant code (
> https://github.com/yatesco/clojure-perf/blob/master/src/inc.clj):
>
> [code]
> (ns inc
>   (:gen-class))
>
> (defn- inc-atom [n]
>   (def x (atom 0))
>   (dotimes [n n] (swap! x inc))
>   @x)
>
> (defn- array-let [n]
>   (let [a (int-array n)]
>     (dotimes [n n] (aset-int a n 1))
>     (areduce a i ret 0
>              (+ ret (aget a i)))))
>
> (defn- array-def [n]
>   (def a (int-array n))
>   (dotimes [n n] (aset-int a n 1))
>   (areduce a i ret 0
>            (+ ret (aget a i))))
>
> (defn- run-test [subject n]
>   (time (do (def x (subject n)) (println x))))
>
> (defn -main [& args]
>   (let [n 1000000]
>     (println "inc atom")
>     (run-test inc-atom n)
>     (println "array with let")
>     (run-test array-let n)
>     (println "array with def")
>     (run-test array-def n))
> )
> [/code]
>
> Interestingly, if I refactored an 'execute-on-array' def which array-let
> and array-def delegated to then they had the same performance which seems
> to imply it is about scoping, but the array in both array-let and array-def
> have exactly the same scope...  Setting the autoboxing warning to true
> didn't point out anything either.
>
> The output (from my VM, so a bit slow):
> [code]
> inc atom
> 1000000
> "Elapsed time: 213.214118 msecs"
> array with let
> 1000000
> "Elapsed time: 75.302602 msecs"
> array with def
> 1000000
> "Elapsed time: 12868.970203 msecs"
> [/code]
>
> For comparison, the following java code:
>
> [code]
> package perf;
>
> public class Inc {
>     public static void main(String[] args) {
>         int n = 1000000;
>         int counter = 0;
>         long start = System.currentTimeMillis();
>         for (int i=0; i<n; i++) counter++;
>         long end  = System.currentTimeMillis();
>         System.out.println ("Naive " + (end - start) + " ms, counter is "
> + counter);
>
>         counter = 0;
>         int[] arr = new int[n];
>         start = System.currentTimeMillis();
>         for (int i=0; i<arr.length; i++) arr[i]=1;
>         for (int i=0; i<arr.length; i++) counter = counter + arr[i];
>         end  = System.currentTimeMillis();
>         System.out.println ("Array " + (end - start) + " ms, counter is "
> + counter);
>                                            }
> }
> [/code]
>
> produces the (as expected, much faster) results :
>
> [code]
> Naive 3 ms, counter is 1000000
> Array 6 ms, counter is 1000000
> [/code]
>
> I am not surprised that the atom/inc takes much longer than 3 ms, but I
> don't understand why the array solution is so much more expensive in
> Clojure?
>
> On a related point - can anyone provide a faster implementation of summing
> up the contents of an array?
>
> A lein project can be found https://github.com/yatesco/clojure-perf,
> 'lein uberjar; java -jar target/*.jar should demonstrate the output.
>
>  --
> --
> 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.
>
>
>

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