Combining Ken and David's tips, this version processes a byte-array of sizd 1920000 in about 13 milliseconds on my machine:
(def buffer-size 1920000) (def array (byte-array buffer-size)) (defn java-like [^bytes cpuArray] (loop [i (int 0)] (if (< i buffer-size) (let [b (aget cpuArray i) g (aget cpuArray (unchecked-add i (int 1))) r (aget cpuArray (unchecked-add i (int 2))) a (aget cpuArray (unchecked-add i (int 3)))] (aset cpuArray i a) (aset cpuArray (unchecked-add i (int 1)) b) (aset cpuArray (unchecked-add i (int 2)) g) (aset cpuArray (unchecked-add i (int 3)) r) (recur (unchecked-add i (int 4))))))) user=> (time (java-like array)) "Elapsed time: 13.648662 msecs" Found something interesting when I tried to emulate how Robert's version aliased 'unchecked-add' as '+': (defn java-like [^bytes cpuArray] (loop [i (int 0)] (if (< i buffer-size) (let [+ unchecked-add b (aget cpuArray i) g (aget cpuArray (+ i (int 1))) r (aget cpuArray (+ i (int 2))) a (aget cpuArray (+ i (int 3)))] (aset cpuArray i a) (aset cpuArray (+ i (int 1)) b) (aset cpuArray (+ i (int 2)) g) (aset cpuArray (+ i (int 3)) r) (recur (+ i (int 4))))))) When I try to compile this, Clojure complains that I'm trying to rebind i, a primitive local, with a value of the wront type in 'recur'. It seems that 'unchecked-add' returns a primitive (note that in the first version, 'recur' happily accepts the return from 'unchecked-add' without coercion), but when 'unchecked-add' is bound to a new name, the return gets boxed. Is this the correct interpretation, or am I missing something? On Jan 28, 9:06 am, David Nolen <dnolen.li...@gmail.com> wrote: > On Fri, Jan 28, 2011 at 10:48 AM, Robert McIntyre <r...@mit.edu> wrote: > > I tried to convert this java code line for line to clojure to compare > > the speed differences, and boy was I surprised! > > > public static void ConvertToAWT(byte[] cpuArray){ > > // Given an array of bytes representing a c-style bgra > > image, > > // converts to a java style abgr image > > int len = java.lang.reflect.Array.getLength(cpuArray); > > for (int i = 0; i < len; i+=4){ > > byte b = cpuArray[i+0]; > > byte g = cpuArray[i+1]; > > byte r = cpuArray[i+2]; > > byte a = cpuArray[i+3]; > > cpuArray[i+0] = a; > > cpuArray[i+1] = b; > > cpuArray[i+2] = g; > > cpuArray[i+3] = r; }} > > > (defn java-like [] > > (loop [i (int 0)] (if (< i buffer-size) > > (let [ + clojure.core/unchecked-add > > b (aget cpuArray i) > > g (aget cpuArray (+ 1 i)) > > r (aget cpuArray (+ 2 i)) > > a (aget cpuArray (+ 3 i))] > > (aset-byte cpuArray i a) > > (aset-byte cpuArray (+ 1 i) b) > > (aset-byte cpuArray (+ 2 i) g) > > (aset-byte cpuArray (+ 3 i) r) > > (recur (int (+ i 4))))))) > > > (defn clojure-like [] > > (doall (flatten (map (fn [[b g r a]] [a b g r]) (partition 4 4 > > cpuArray))))) > > I'm assuming you're using 1.2.0. cpuArray needs to be hinted. All the > literals also need to be hinted. Don't use aset-byte, use aset. > > In 1.3.0 you no longer have to hint the literals and you can use the > *unchecked-math* compiler flag instead of redefining unchecked-add as a > local. > > David -- 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