2009/10/19 Christophe Grand <christo...@cgrand.net> > Hi, > > On Mon, Oct 19, 2009 at 7:59 AM, harto > <stuart.william.campb...@gmail.com>wrote: > >> I've just started learning Clojure, so I'm trying to figure out the >> correct way of doing things. I've been trying to create and 'modify' a >> large vector for an online programming exercise, but I'm running into >> some performance issues. >> >> Any general tips would be appreciated! >> >> Firstly, I'm creating a vector of booleans like this: >> >> (defn vector-of [n value] >> (vec (for [_ (range n)] value))) >> >> It takes quite a long time for large values of n, though: >> >> user=> (time (dorun (vector-of 1e7 true))) >> "Elapsed time: 6734.509528 msecs" >> > > You don't need dorun here: dorun is sometimes used in benchmarks to force > the computation of lazy-seqs but here you are using a vector, not a lazy > seq. So calling dorun on it causes the allocation of a seq of 1e7 items > which takes time. If you used dorun to prevent the printing of the vector at > the REPL, just di (tcime (count (vector-of 1e7 true))). See: > user=> (time (dorun (vector-of 1e7 nil))) > "Elapsed time: 4155.616985 msecs" > nil > user=> (time (count (vector-of 1e7 nil))) > "Elapsed time: 2384.609217 msecs" > 10000000 >
OK, thanks. I thought I'd need dorun to get a true benchmark because I was using those intermediate lazy sequences. But, it looks like I was misusing those anyway :) > > If you study your function: > (defn vector-of [n value] > (vec (for [_ (range n)] value))) > > You'll see that to create a vector of n items you use two intermediate seqs > of size n items (range and the result of for). > If you get rid of some allocations, you'll get huge speed-ups. > > (defn vector-of [n value] > (loop [n (int n) v []] > (if (zero? n) > v > (recur (dec n) (conj v value))))) > > user=> (time (count (vector-of 1e7 nil))) > "Elapsed time: 1170.371793 msecs" > 10000000 > > Since you don't care about intermediate values of v, you can use > transients: > (defn vector-of [n value] > (loop [n (int n) v (transient [])] > (if (zero? n) > (persistent! v) > (recur (dec n) (conj! v value))))) > > user=> (time (count (vector-of 1e7 nil))) > "Elapsed time: 228.272239 msecs" > 10000000 > > > >> Secondly, I'm iterating across one of these large vectors using >> something like the following (contrived) function: >> >> (defn set-flags [v] >> (loop [i 0 >> v v] >> (if (< i (count v)) >> (recur (inc i) (assoc v i false)) >> v))) >> >> user=> (let [v (vector-of 1e7 true)] (time (dorun (set-flags v)))) >> "Elapsed time: 15563.916114 msecs" >> >> > For reference (using my fastest vector-of): > user=> (let [v (vector-of 1e7 true)] (time (count (set-flags v)))) > "Elapsed time: 5653.562953 msecs" > 10000000 > > Here too you don't care about intermediate values of v: > (defn set-flags [v] > (loop [i 0 v (transient v)] > (if (< i (count v)) > (recur (inc i) (assoc! v i false)) > (persistent! v)))) > > user=> (let [v (vector-of 1e7 true)] (time (count (set-flags v)))) > "Elapsed time: 1423.473584 msecs" > 10000000 > > And if you store (count n) in a local: > (defn set-flags [v] > (let [n (count v)] > (loop [i 0 v (transient v)] > (if (< i n) > (recur (inc i) (assoc! v i false)) > (persistent! v))))) > > user=> (let [v (vector-of 1e7 true)] (time (count (set-flags v)))) > "Elapsed time: 931.911668 msecs" > 10000000 > Thanks very much. I wasn't aware of transients until reading this. In fact, I had to search the Clojure website to find the relevant page ( http://clojure.org/transients). Cheers! > > hth, > > Christophe > > > > -- > Professional: http://cgrand.net/ (fr) > On Clojure: http://clj-me.blogspot.com/ (en) > > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---