Skip to content

Instantly share code, notes, and snippets.

@vasily-kirichenko
Created November 1, 2012 10:13
Show Gist options
  • Save vasily-kirichenko/3992893 to your computer and use it in GitHub Desktop.
Save vasily-kirichenko/3992893 to your computer and use it in GitHub Desktop.
Multimethods vs Protocols
(defrecord Order [price])
;; protocol
(defprotocol Calculable
(p-total [this]))
(extend-protocol Calculable
Order
(p-total [order] (:price order))
clojure.lang.IPersistentMap
(p-total [m] (:price m)))
;; multimethod that accesses the object as a map
(defmulti m-map-total class)
(defmethod m-map-total Order [order] (:price order))
(defmethod m-map-total clojure.lang.IPersistentMap [m] (:price m))
;; multimethod that accesses the object as a class
(defmulti m-class-total class)
(defmethod m-class-total Order [order] (.price order))
;; test
(defn measure
[constructor type]
(let [orders (reduce conj (for [n (range 3000000)] (constructor n)) ())]
(prn (format "created %s %ss." (count orders) type))
(doseq [[f msg] [[:price "direct (map)"]
[p-total "protocol"]
[m-map-total "multimethod (map)"]
[#(.price %) "direct (class)"]
[m-class-total "multimethod (class)"]]]
(prn (format
"%s: %s msecs."
msg
(try
(tc (dorun (map f orders)))
(catch Exception ex (str ex))))))))
(measure #(Order. %) "order")
(measure #(hash-map :price %) "map")
; created 3000000 orders.
; direct (map): 261.759601 msecs.
; protocol: 227.293889 msecs.
; multimethod (map): 330.989975 msecs.
; direct (class): 6391.209907 msecs.
; multimethod (class): 6412.286282 msecs.
;
; created 3000000 maps.
; direct (map): 289.209819 msecs.
; protocol: 329.602042 msecs.
; multimethod (map): 645.605847 msecs.
; direct (class): -
; multimethod (class): -
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment