On Dec 28, 2010, at 8:57 PM, Mark Engelberg wrote:

Just for fun, I was curious to see what it would be like,
performance-wise, to simulate a synchronized mutable hash map by
putting a clojure hash map inside an atom, and making this accessible
to Java code via the map interface.

I didn't try to implement the entire map interface, but just the major
things for testing purposes.  The code is below.

Benchmarking insertions on my machine, I'm seeing that the Clojure
code (Clojure 1.2, java -server) takes roughly 8-20x longer (depending
on how large the hashmap is).

To test, for example, I do something like
(def ^com.justforfun.NonBlockingHashMap h (com.justforfun.NonBlockingHashMap.))
(def ^java.util.Map j (. java.util.Collections synchronizedMap
(java.util.HashMap.)))

(time (doseq [i (range 100000)] (.put h i 2)))   ;900ms
(time (doseq [i (range 100000)] (.put j i 2)))    ;70ms

Does this seem reasonable, or is there a better way to do this test?
Frankly, I was expecting Clojure's numbers to compare a bit more
favorably.

You need to compare against j.u.c.ConcurrentHashMap. It exists because the locking strategy used by synchronizedMap doesn't scale well. You won't even see that overhead on simplistic benchmarks like yours because the optimizer can likely see the map never escapes and can remove all the locking.

Here's a more realistic comparison:

(definterface M
  (put [k v])
  (get [k]))

(defn ^M h []
  (let [m (atom {})]
    (reify M
           (put [_ k v] (swap! m assoc k v))
           (get [_ k] (get @m k)))))

(defn ^java.util.Map j []
  (java.util.concurrent.ConcurrentHashMap.))

(let [v (into [] (range 100000))]
  (dotimes [_ 10]
    (let [h (h)
          j (j)]
      (println "adding")
      (time (doseq [i v] (.put h i 2)))
      (time (doseq [i v] (.put j i 2)))
      (println "lookup")
      (time (doseq [i v] (.get h i)))
      (time (doseq [i v] (.get j i))))))

adding
"Elapsed time: 96.351 msecs"
"Elapsed time: 46.474 msecs"
lookup
"Elapsed time: 30.424 msecs"
"Elapsed time: 28.3 msecs"
adding
"Elapsed time: 98.647 msecs"
"Elapsed time: 46.578 msecs"
lookup
"Elapsed time: 32.284 msecs"
"Elapsed time: 32.531 msecs"
adding
"Elapsed time: 293.863 msecs"
"Elapsed time: 34.284 msecs"
lookup
"Elapsed time: 18.632 msecs"
"Elapsed time: 15.416 msecs"
adding
"Elapsed time: 95.019 msecs"
"Elapsed time: 33.441 msecs"
lookup
"Elapsed time: 19.4 msecs"
"Elapsed time: 16.265 msecs"
adding
"Elapsed time: 89.819 msecs"
"Elapsed time: 31.929 msecs"
lookup
"Elapsed time: 19.574 msecs"
"Elapsed time: 14.87 msecs"
adding
"Elapsed time: 94.126 msecs"
"Elapsed time: 33.812 msecs"
lookup
"Elapsed time: 20.514 msecs"
"Elapsed time: 14.957 msecs"
adding
"Elapsed time: 427.7 msecs"
"Elapsed time: 32.465 msecs"
lookup
"Elapsed time: 18.858 msecs"
"Elapsed time: 14.848 msecs"
adding
"Elapsed time: 91.149 msecs"
"Elapsed time: 32.392 msecs"
lookup
"Elapsed time: 19.491 msecs"
"Elapsed time: 15.441 msecs"
adding
"Elapsed time: 91.648 msecs"
"Elapsed time: 33.283 msecs"
lookup
"Elapsed time: 19.113 msecs"
"Elapsed time: 15.028 msecs"
adding
"Elapsed time: 90.503 msecs"
"Elapsed time: 31.736 msecs"
lookup
"Elapsed time: 19.557 msecs"
"Elapsed time: 15.082 msecs"



--
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

Reply via email to