(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]))))
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.
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 clo...@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+unsubscribe@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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
I'll bet the atom accesses dominate the computation. They are a part of Clojures software transactional memory (STM) and have a cost.
(deftype point5 [^long i ^long j]
Object
(equals [this that] (and (= (.i this) (.i ^point5 that))
(= (.j this) (.j ^point5 that))))
(hashCode [this] (+ (.i this) (* 4000 (.j this)))))
(defn iter-neighbors5 [f ^point5 p]
(let [i ^long (.i p)
j ^long (.j p)]
(f (->point5 (dec i) j))
(f (->point5 (inc i) j))
(f (->point5 i (dec j)))
(f (->point5 i (inc j)))))
(defn nth5 [n p]
(loop [n ^long n
s1 (HashSet. [p])
s2 (HashSet.)]
(if (zero? n)
s1
(let [s0 (HashSet.)]
(letfn [(add [p]
(when (not (or (.contains s1 p) (.contains s2 p)))
(.add s0 p)))]
(doseq [p s1] (iter-neighbors5 add p))
(recur (dec n) s0 s1))))))
Here's the run down from slowest to fastest with a size of 100 using criterium. All of them I did my best to avoid reflection and boxed numeric and had enabled uncheck math. Granted I did not find that boxing and unchecked math really provided a drastic improvement in my case.:
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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
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+unsubscribe@googlegroups.com.
On Nov 21, 2016, at 3:05 PM, Didier <did...@gmail.com> wrote:I experimented with this a lot, and took everyone's advice, and this is the fastest I got, even faster then Michael Gardner's answer.
(deftype point5 [^long i ^long j]
Object
(equals [this that] (and (= (.i this) (.i ^point5 that))
(= (.j this) (.j ^point5 that))))
(hashCode [this] (+ (.i this) (* 4000 (.j this)))))
--
On Nov 21, 2016, at 8:03 PM, Didier <did...@gmail.com> wrote:@miner: Doesn't using the flag (set! *unchecked-math* :warn-on-boxed) gives me unchecked math automatically? I was under the impression that +, -, /, * etc. would all now perform in an equal way to unchecked-add, etc. If not, what is the difference?
--