Below is the fastest version I tested, using ideas from the various responses in this thread. It runs in ~4s on my machine, compared with ~27s for the original version.
The biggest win by far was from James Reeves' suggestion of switching to Java's mutable HashSet. I'm not sure why; I'd thought that using transients and transducers with Clojure's native sets would provide comparable performance, but this was not true in my testing. I also couldn't figure out how to avoid the reflection warning when invoking HashSet's constructor that takes a generic Collection, which is why that ugly doto is there in nth-neighbors. How would I avoid that? (ns hash-set-bench (import [java.util HashSet] [java.awt Point])) (set! *warn-on-reflection* true) (set! *unchecked-math* :warn-on-boxed) (defn neighbors [^Point p] (let [x (.-x p), y (.-y p)] [(Point. x (inc y)) (Point. x (dec y)) (Point. (inc x) y) (Point. (dec x) y)])) (defn nth-neighbors [^long n ^Point p] (loop [n n, s1 (doto (HashSet.) (.add p)), s2 (HashSet.)] (if (zero? n) s1 (let [s0 (HashSet.)] (doseq [_ s1, p (neighbors _)] (when-not (or (.contains s1 p) (.contains s2 p)) (.add s0 p))) (recur (dec n) s0 s1))))) > On Nov 15, 2016, at 19:39, Didier <didi...@gmail.com> wrote: > > Hey all, > > I came upon a benchmark of F#, Rust and OCaml, where F# performs much faster > then the other two. I decided for fun to try and port it to Clojure to see > how Clojure does. Benchmark link: https://github.com/c-cube/hashset_benchs > > This is my code for it: > https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a > > (ns hash-set-bench > "A Benchmark I modified to Clojure from: > https://github.com/c-cube/hashset_benchs") > > (defn iterNeighbors [f [i j]] > (f [(dec i) j]) > (f [(inc i) j]) > (f [i (dec j)]) > (f [i (inc j)])) > > (defn nth* [n p] > (loop [n n s1 #{p} s2 #{}] > (if (= n 0) > s1 > (let [s0 (atom #{})] > (letfn [(add [p] > (when (not (or (contains? s1 p) (contains? s2 p))) > (reset! s0 (conj @s0 p))))] > (doseq [p s1] (iterNeighbors add p)) > (recur (dec n) @s0 s1)))))) > > #_(printf "result is %d" (count (time (nth* 2000 [0 0])))) > > And here's the F# code: > https://github.com/c-cube/hashset_benchs/blob/master/neighbors2.fsx > > Currently, this takes about 30s in Clojure, while it only takes around 3s for > OCaml, Rust and F#. > > From what I see, the differences between my code and theirs are: > • Lack of a Point struct, I'm just using a vector. > • They use a mutable set, I don't. > • They overrode Hashing for their point struct, as well as equality. I > rely on Clojure's default hashing, and vector equality. > I'm not sure if any of these things should really impact performance that > much though. And what I could do in Clojure if I wanted to improve it. > > > > Any Help? > > > > Thanks. > > > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.