As far as I can tell there is currently no way to hint 2d array access fast (def a (make-array Double/TYPE 100 100)) (time (doseq [i (range 100), j (range 100)] (aget a (int i) (int j)))) "Elapsed time: 836.800335 msecs" I can't find any combination of type hinting to speed it up.
However with a trivial change to core.clj [just added (int idx) in the multi-arg case]: > (apply aget (aget array (int idx)) idxs))) (time (doseq [i (range 100), j (range 100)] (aget a i j))) "Elapsed time: 40.162875 msecs" It is fast! Yay! That's great, almost as fast as a 1d array: (def b (make-array Double/TYPE 10000)) (time (doseq [i (range 100), j (range 100)] (aget b (int (+ i (* j 100)))))) "Elapsed time: 27.701047 msecs" But still it seems for maximum speed you would go with a 1d array. Now for 1d arrays, the index also cannot be anything other than an integer, so we could do the same thing [just added (int ~i)]: {:inline (fn [a i] `(. clojure.lang.RT (aget ~a (int ~i)))) (time (doseq [i (range 100), j (range 100)] (aget b (+ i (* j 100))))) "Elapsed time: 27.701047 msecs" Great, it is just as fast as when we had to coerce to int. But the coercion comes at a small cost when we don't need it: (time (amap b idx ret (aset ret idx (inc (aget b idx))))) original: "Elapsed time: 23.06673 msecs" modified: "Elapsed time: 27.457263 msecs" <-- slower :( :( :( So for the 1d case for maximum speed it appears better to leave it to the user to coerce when necessary. The index must be an integer - is there any way to have this fast in both cases? If not another alternative would be to have an aget* and aget be a macro that coerces, to allow both forms. For multi-dimensional it appears the coercion must (and should) happen in core? Then I came across this post by cgrand: http://clj-me.cgrand.net/2009/08/06/what-warn-on-reflection-doesnt-tell-you-about-arrays/ Indicates that type-hinting the array itself can provide a significant speed-up, but I don't understand why, is this just more reflection or is something else going on here? In theory it should be possible to create a macro that creates automatically type-hinted arrays (seeing the type is passed in) the trick being to convert the type to a hint string. How would I do that? And finally, it is actually faster to have an array of Objects and store doubles in them than to use an array of doubles (due to boxing I think). In my experimentation about 10% faster. Presumably an array of doubles would be far less memory however. (time (let [a #^"[Ljava.lang.Object;" (make-array Object 100)] (dotimes [i 10000000] (aget a (int (rem i 100)))))) "Elapsed time: 3825.546843 msecs" (time (let [a #^doubles (make-array Double/TYPE 100)] (dotimes [i 10000000] (aget a (int (rem i 100)))))) "Elapsed time: 4246.330734 msecs" I know micro-benchmarks can be misleading, thanks for reading - please point out any errors I've made. Regards, Tim. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---