Thanks Jim and David.

David, can you expand on why it is incorrect?  That is such a strong word.
 Is it correct but simply non-idiomatic?

Also note that if I move the body out of the 'let' version of the array
into another function passing in the array then the performance is the same
as the 'def' version, so even if def is a problem it isn't the only cause.



On 21 June 2013 14:29, David Nolen <[email protected]> wrote:

> 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 <[email protected]>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 [email protected]
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> [email protected]
>> 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 [email protected].
>>
>> 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 [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/cvWf502OVPo/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> 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 [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to