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.