Browse files

CLJS-499: Reassess ObjMap vs. PersistentArrayMap

Deprecate ObjMap.

ObjMap was introduced as optimization to leverage the performance
benefits around JS Objects for access. However in order to avoid
issues around possible prototype modification of Object as well as the
performance hit of hasOwnProperty, ObjMap relied on an internal array
for determining the presence of a key - every lookup call involves a
scan, just like PersistentArrayMap.

Because of the extra array, modifying an ObjMap required considerably
more work.

PersistentArrayMap has been tuned following the enhancements made to
Clojure's PersistentArrayMap. PersistentArrayMap on V8 has as good as
or faster lookup times than ObjMap, and modification times are up to
>9X faster according to our benchmark suite. JavaScriptCore also shows
performance benefits though they are not as dramatic. On Firefox the
performance is degraded but in general Firefox lags considerably on
all ClojureScript benchmarks.

As it turns out most users were likely already using PersistentArrayMap by
default as there was a compiler emission bug, only empty maps compiled
to ObjMap.

Fixed bug in TransientHashMap logic, we use
cljs.core.PersistentHashMap/EMPTY rather than the empty map literal.
  • Loading branch information...
swannodette committed May 20, 2013
1 parent 5585bf3 commit 08489f39060be1097fa23abc8d5042c86e68dd4d
Showing with 4 additions and 13 deletions.
  1. +1 −10 src/clj/cljs/compiler.clj
  2. +3 −3 src/cljs/cljs/core.cljs
@@ -232,16 +232,7 @@
(emit-wrap env
(zero? (count keys))
- (emits "cljs.core.ObjMap.EMPTY")
- (and simple-keys? (<= (count keys) obj-map-threshold))
- (emits "cljs.core.ObjMap.fromObject(["
- (comma-sep keys) ; keys
- "],{"
- (comma-sep (map (fn [k v]
- (with-out-str (emit k) (print ":") (emit v)))
- keys vals)) ; js obj
- "})")
+ (emits "cljs.core.PersistentArrayMap.EMPTY")
(<= (count keys) array-map-threshold)
(emits "cljs.core.PersistentArrayMap.fromArray(["
@@ -3784,7 +3784,7 @@ reduces them without incurring seq initialization"
(recur (inc i) (assoc! out k (aget so k))))
(with-meta (persistent! (assoc! out k v)) mm)))))
-;;; ObjMap
+;;; ObjMap - DEPRECATED
(defn- obj-clone [obj ks]
(let [new-obj (js-obj)
@@ -4162,10 +4162,10 @@ reduces them without incurring seq initialization"
(throw (js/Error. "dissoc! after persistent!")))))
-(declare TransientHashMap)
+(declare TransientHashMap PersistentHashMap)
(defn- array->transient-hash-map [len arr]
- (loop [out (transient {})
+ (loop [out (transient cljs.core.PersistentHashMap/EMPTY)
i 0]
(if (< i len)
(recur (assoc! out (aget arr i) (aget arr (inc i))) (+ i 2))

0 comments on commit 08489f3

Please sign in to comment.