Hi All, I stuck with performance problem using Clojure. It seems that when all the optimisation hints are used, Clojure data processing is still much slower than Java.
In my simple test I sum up 16M of random integers 0 < n < 10. The code is as follows (see below Java and C code, and the test script and output): (def *N* (* 1024 1024 16)) (def *a* (make-array Integer/TYPE *N*)) (dotimes [i *N*] (aset ^ints *a* i (int (* 10 (rand 1.0))))) (set! *warn-on-reflection* true) (defn sum [arr] (loop [i (int 0) s (int 0)] (if (= i *N*) s (recur (inc i) (+ s (aget ^ints arr i)))))) (println "Clojure:" *clojure-version*) (dotimes [_ 5] (time (println "sum =" (sum *a*)))) (set! *warn-on-reflection* false) In this test Clojure is ~15 times slower than the same test in plain Java. (The best result is for Clojure 1.2, it's slower for the 1.3-alpha version, see the output log below.) I didn't use there unchecked-inc, unchecked-add, but it doesn't help much either. Actually, this is even not about access to the Java array, because the sum of constants (1+1+1... ) is evaluated at nearly the same time (30% more quick, ~10 time slower than the original test in Java). It's rather surprising, having in mind that Clojure code is compiled to the bytecode, pretty much the same as Java code is. I do realize that Java demonstrates an extremely powerful JIT technic there, since the loop is executed in just ~1 nanosecond which is ~3 CPU cycles on my PC. (Clojure's best result shows ~16ns = ~50 CPU cycles.) Although, the same slowdown I observed with more sophisticated tests, therefore it seems to be a general trend. Thanks in advance, I would appreciate very much any suggestions or comments. Best wishes, Dmitriy P.S. The code for Java/Clojure/C languages, test script, and its output: ### Sum.java ############################################### package Test; import java.util.Random; public class Sum { public static void main(String args[]) { int N = 1024*1024*16; int a[] = new int[N]; int i, cs = 0; Random r = new Random(); for(i = 0; i < N; i++) { int r_int = r.nextInt(); a[i] = (r_int > 0 ? r_int : -r_int) % 10; } for(int l = 0; l < 5; l++) { long start = System.currentTimeMillis(); cs = 0; for(i = 0; i < N; i++) { cs += a[i]; } System.out.printf("Elapsed time (Java): %1$d msecs\n", System.currentTimeMillis() - start); } System.out.printf("sum = %1$d\n", cs); } } ### sum.clj ############################################### (def *N* (* 1024 1024 16)) (def *a* (make-array Integer/TYPE *N*)) (dotimes [i *N*] (aset ^ints *a* i (int (* 10 (rand 1.0))))) (set! *warn-on-reflection* true) (defn sum [arr] (loop [i (int 0) s (int 0)] (if (= i *N*) s (recur (inc i) (+ s (aget ^ints arr i)))))) (println "Clojure:" *clojure-version*) (dotimes [_ 5] (time (println "sum =" (sum *a*)))) (set! *warn-on-reflection* false) ### sum.c ############################################### #include <stdlib.h> #include <stdio.h> #include <math.h> #include <sys/time.h> #define N (1024*1024*16) int a[N]; int main() { int i, cs = 0; struct timeval t1, t2; srand(23); for(i = 0; i < N; i++) { int rn = rand(); a[i] = rn % 10; } gettimeofday(&t1, NULL); for(i = 0; i < N; i++) { cs += a[i]; } gettimeofday(&t2, NULL); printf("Elapsed time (C): %d msecs\n", (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000); printf("sum = %d\n", cs); } ### test-sum.sh ############################################### #! /bin/bash echo System info: cat /proc/cpuinfo | grep 'model name' | tail -1 uname -rs # C echo gcc --version gcc -O2 -o sum sum.c ./sum # Java echo javac -6 Test/Sum.java java -version java -server -cp . Test.Sum # Clojure 1.2 alpha echo java -server -cp .:clojure.jar clojure.main sum.clj # Clojure 1.3 alpha echo java -server -cp .:clojure-1.3a.jar clojure.main sum.clj # clean rm sum Test/Sum.class ### The output: ############################################### System info: model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz Linux 2.6.27.19-170.2.35.fc10.i686 gcc (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7) Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Elapsed time (C): 14 msecs sum = 75480349 java version "1.6.0_0" OpenJDK Runtime Environment (IcedTea6 1.6) (fedora-23.b16.fc10-i386) OpenJDK Server VM (build 14.0-b16, mixed mode) Elapsed time (Java): 17 msecs Elapsed time (Java): 19 msecs Elapsed time (Java): 14 msecs Elapsed time (Java): 17 msecs Elapsed time (Java): 18 msecs sum = 75490326 Clojure: {:major 1, :minor 2, :incremental 0, :qualifier } sum = 75488840 "Elapsed time: 568.937934 msecs" sum = 75488840 "Elapsed time: 285.198714 msecs" sum = 75488840 "Elapsed time: 293.939893 msecs" sum = 75488840 "Elapsed time: 291.059807 msecs" sum = 75488840 "Elapsed time: 299.875087 msecs" Clojure: {:major 1, :minor 3, :incremental 0, :qualifier alpha1} sum = 75479971 "Elapsed time: 683.505713 msecs" sum = 75479971 "Elapsed time: 528.660321 msecs" sum = 75479971 "Elapsed time: 499.890406 msecs" sum = 75479971 "Elapsed time: 485.581542 msecs" sum = 75479971 "Elapsed time: 474.028165 msecs" -- 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