I wanted to do some real-time graphics rendering and was trying to do multiple calculations per pixel per frame. I then quickly noticed that this was very slow and started at the very base: how fast can I loop over all the pixels?
I found dotimes reasonably fast, but when I do this in a REPL it is awfully slow:
user=> (dotimes [_ 10] (time (dotimes [_ 1e7] (+ 1 1))))
"Elapsed time: 409.177477 msecs"
"Elapsed time: 417.755502 msecs"
"Elapsed time: 418.939182 msecs"
"Elapsed time: 420.131575 msecs"
"Elapsed time: 419.83529 msecs"
"Elapsed time: 417.612003 msecs"
"Elapsed time: 420.749229 msecs"
"Elapsed time: 418.918554 msecs"
"Elapsed time: 414.403957 msecs"
"Elapsed time: 417.729624 msecs"
nil
user=>
Then I put this into a Leiningen project. When I do a "lein run" it is just as slow. But when I create the uberjar and run it with the java command it's a lot faster:
% java -jar target/looping-0.1.0-SNAPSHOT-standalone.jar
"Elapsed time: 122.006758 msecs"
"Elapsed time: 3.667653 msecs"
"Elapsed time: 3.60515 msecs"
"Elapsed time: 4.008436 msecs"
"Elapsed time: 3.961558 msecs"
"Elapsed time: 3.60212 msecs"
"Elapsed time: 3.592532 msecs"
"Elapsed time: 4.573949 msecs"
"Elapsed time: 3.959568 msecs"
"Elapsed time: 3.607495 msecs"
Although the first run is still a lot slower. What is the difference? In both cases the code is compiled, there is no interpreted Clojure, right? Is it JIT, some optimizations or some special JVM options that are set for the REPL?
Thanks for any ideas.