<< Back to previous view

[CLJS-1648] Getting Source Info into ex-info data for Analysis Errors. Created: 25/May/16  Updated: 25/May/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Bruce Hauman Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: error-reporting, repl

Attachments: Text File CLJS-1648.patch    

 Description   

With an eye towards improving Analysis Error messages in the REPL.

It would be nice to have the original source of the evaluated form available in the ex-data of the Analysis Error.



 Comments   
Comment by Bruce Hauman [ 25/May/16 12:52 PM ]

This patch is working fine.





[CLJS-1593] Self-host: Munged minus macro Created: 25/Feb/16  Updated: 25/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bootstrap


 Description   

In bootstrap, the macro form of cljs.core/- is evidently available as _ so, for example

(_ 7 3)
works.

Repro:

cljs.user=> (require 'cljs.js)
nil
cljs.user=> (cljs.js/eval-str (cljs.js/empty-state)
  "(_ 7 3)" nil {:eval cljs.js/js-eval :context :expr} identity)
{:ns cljs.user, :value 4}





[CLJS-1549] Printing #object tags should be consistent Created: 22/Jan/16  Updated: 29/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Antonin Hildebrand Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_1549.patch    
Patch: Code

 Description   

[CLJS-1376|http://dev.clojure.org/jira/browse/CLJS-1376) wanted to bring printing parity with Clojure 1.7.0.

There are two problems:
1) Atom and Volatile contain extra space between #object and "[" (that differs from Clojure 1.7.0)
2) Atom and Volatile printing was inconsistent with #object printing in pr-writer-impl (in goog/isFunction and :else branches) - there we have no space

I have introduced a function which handles printing object tags consistently without space. Also I have broken writing content into writer into logical tokens for easier cljs-devtools implementation.

Background info:
Exact printing behaviour is quite important for me when implementing alternative pr-writer-impl for cljs-devtools. For most cases I call original pr-writer-impl and then post-process its output to enhance its presentation in DevTools console:
https://github.com/binaryage/cljs-devtools/blob/2f1c0f4095a364bb11a833e73e5753a4e48add8f/src/devtools/format.cljs#L200-L226

In case of constructors or functions (goog/isFunction and :else branches of pr-writer-impl), I don't want to emit stringified content, but I want to provide real js-object reference and delegate further printing/expansion to native javascript formatter in DevTools.
In other cases like Atom or Volatile, I would like to easily detect "#object" as first token written into writer and provide better visual clues. I find printing "#object [...]" confusing for more complex data situations. Square brackets resemble vectors and may confuse clarity. Instead I will use color-coding or another form of visual styling to mark object instances and their boundaries. But for this I want to have nice token stream "#object" "[" ... "]" without having to use regexps.






[CLJS-1533] Null pointer error on non-existent file in advanced mode Created: 01/Jan/16  Updated: 01/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Glen Mailer Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: error-reporting


 Description   

When building without optimisations, having a foreign-lib point to a non-existent file gives a fairly clear FileNotFoundException

When doing the same build but with advanted optimisations, the much more cryptic error java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil is given

Repo with code that reproduces and full bash output is here: https://gist.github.com/glenjamin/2614f71a50dbbccf9040






[CLJS-1450] Arithmetic warning thrown for impossible condition Created: 15/Sep/15  Updated: 30/Mar/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Quest Yarbrough Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, compiler


 Description   

The following code triggers an arithmetic warning even though the condition it's warning about is impossible to reach. I tested this code in Clojure and it did not generate a warning. I would guess that the CLJS compiler doesn't take note of the (js/Error) in the same way that the Clojure compiler treats (Error.)

The exact warning triggered is below, followed by the code.

WARNING: cljs.core/+, all arguments must be numbers, got [number clj-nil] instead. at line 22 src\spurious_arithmetic\core.cljs
(def x [0 1 2 3 4 nil])
(def index (atom -1))
(defn take-value []
  (->> (swap! index inc)
       (nth x)))

(-> (loop [result (take-value)
           prev nil]
      (if (= nil result prev) (throw (js/Error. "This condition prevents nil arithmetic.")))
      (if (some? result)
        (recur (take-value) result)
        (+ 1 prev)))                                        ; this triggers the [number cljs-nil] warning
    (print)) ; 5


 Comments   
Comment by Mike Fikes [ 30/Mar/16 11:33 PM ]

The type inference logic in the compiler expects that the type of a loop local is static. In fact, somewhat the opposite of this ticket is being done in CLJS-1561.





[CLJS-1378] JARs that end in .exe are problematic Created: 29/Jul/15  Updated: 30/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3308
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

compile-from-jar cannot handle the later form

{{jar:file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.jar!/cljs/com/walmart/test/app.cljs}}
{{jar:file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.exe!/cljs/com/walmart/test/app.cljs}}






[CLJS-1364] cljs.js: Update default *load-fn* args to reflect docstring Created: 23/Jul/15  Updated: 14/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1364-1.patch    

 Description   

The default *load-fn* :

(fn [name cb]
    (throw (js/Error. "No *load-fn* set")))

But the name arg reflects an older impl, with the new arg actually being a map.

To avoid confusion for anyone reading this code, perhaps

(fn [_ _]
    (throw (js/Error. "No *load-fn* set")))

or maybe name the first argument something meaningful?



 Comments   
Comment by Andrea Richiardi [ 18/Dec/15 6:52 PM ]

I decided to give it a try





[CLJS-1344] port Clojure tuples commit Created: 17/Jul/15  Updated: 11/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: Next

Type: Task Priority: Trivial
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-CLJS-1344-port-Clojure-tuples-commit-of-16-July-2015.patch     Text File 0002-CLJS-1344-port-Clojure-tuples-commit-of-16-July-2015.patch     Text File 0003-CLJS-1344-port-Clojure-tuples-commit-of-16-July-2015.patch    

 Description   

See https://github.com/clojure/clojure/commit/36d665793b43f62cfd22354aced4c6892088abd6



 Comments   
Comment by Michał Marczyk [ 18/Jul/15 11:38 AM ]

Patch based on current master.

Comment by Michał Marczyk [ 18/Jul/15 11:50 AM ]

In absence of abstract bases macros seemed like the most straightforward way to keep things DRY. Anything involving transients or metadata still uses PV, as in Clojure.

Comment by Michał Marczyk [ 18/Jul/15 12:04 PM ]

The 0002 patch is the same, except it does NOT change PV's -equiv to check satisfies? IVector rather than instance? PersistentVector. (The 0001 patch does make this change.)

Haven't made up my mind as to whether it's better to switch or not, so I thought I'd prepare both versions.

Comment by Michał Marczyk [ 18/Jul/15 12:25 PM ]

Some benchmark results, for now obtained using SpiderMonkey (I've just realized that I don't have a working V8 setup on this box – which is not the one I normally use for CLJS dev – I'll have to look into fixing that).

On the subject of -equiv, script benchmark says 0002 patch is very slightly faster than 0001 patch, which itself is noticeably faster than master: 633 ms vs 660 ms vs 781 ms in the vector equality benchmark.

The reason both patches are faster than master is undoubtedly their choice to call -count rather than count on the "other thing"; that is 100% justified in the 0002 patch (with instance?) and slightly less justified in the 0001 patch (who could implement IVector without ICounted though?).

Full script/benchmark results:

master
======

Benchmarking with SpiderMonkey
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 585 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 137 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 735 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 3 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 297 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 23 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 21 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 32 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 524 msecs
[coll "foobar"], (seq coll), 1000000 runs, 1879 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 789 msecs
[coll "foobar"], (first coll), 1000000 runs, 1762 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 150 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 1297 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 587 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 1486 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 105 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 214 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 114 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 111 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 88 msecs
[], (list), 1000000 runs, 13 msecs
[], (list 1 2 3), 1000000 runs, 1691 msecs

;;; vector ops
[], [], 1000000 runs, 9 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 715 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0xd0fabc8 "cljs.tagged_literals.JSValue@d0fabc8"])), 1000000 runs, 972 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 638 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 161 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 323 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 361 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 238 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 211 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 1284 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 1071 msecs
[coll []], (-conj coll 1), 1000000 runs, 1067 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 1133 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 835 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 472 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 557 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 91 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 104 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 690 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 435 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 425 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 251 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 160 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 213 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 184 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 207 msecs
[], (-next v), 1000000 runs, 768 msecs
[], (-rest v), 1000000 runs, 326 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 679 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 781 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 672 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 965 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 403 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 20 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 267 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 675 msecs
[], (list 1 2 3 4 5), 1000000 runs, 639 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 2422 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 1725 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 1620 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 3240 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 2525 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 2980 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 453 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 549 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 265 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 1695 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 276 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 252 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 2831 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 373 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 276 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 515 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 320 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 355 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 322 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 297 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 416 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 360 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 331 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 894 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 732 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 1027 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 699 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 589 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 330 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 523 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 307 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 530 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 295 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 574 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 291 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 280 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 9 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 251 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 253 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 322 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 336 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 373 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 626 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 266 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 244 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 267 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 340 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 128 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 111 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 361 msecs
[coll pmap], (:f0 coll), 1000000 runs, 385 msecs
[coll pmap], (get coll :f0), 1000000 runs, 370 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 324 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 364 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 3598 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 657 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 565 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 421 msecs

transient map, conj! 100000 items
"Elapsed time: 539 msecs"


;;; set ops
[], #{}, 1000000 runs, 217 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 587 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 477 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 304 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 267 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 289 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 21 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 85 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 1060 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 77 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 369 msecs
;;; second run
[r r], (last r), 1 runs, 94 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 233 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 473 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 1233 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 688 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 53 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 52 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 177 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1298 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 57 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 569 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 67 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 82 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 134 msecs

0001 patch
==========

Benchmarking with SpiderMonkey
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 585 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 137 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 735 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 3 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 297 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 23 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 21 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 32 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 524 msecs
[coll "foobar"], (seq coll), 1000000 runs, 1879 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 789 msecs
[coll "foobar"], (first coll), 1000000 runs, 1762 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 150 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 1297 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 587 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 1486 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 105 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 214 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 114 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 111 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 88 msecs
[], (list), 1000000 runs, 13 msecs
[], (list 1 2 3), 1000000 runs, 1691 msecs

;;; vector ops
[], [], 1000000 runs, 9 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 715 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0xd0fabc8 "cljs.tagged_literals.JSValue@d0fabc8"])), 1000000 runs, 972 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 638 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 161 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 323 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 361 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 238 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 211 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 1284 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 1071 msecs
[coll []], (-conj coll 1), 1000000 runs, 1067 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 1133 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 835 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 472 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 557 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 91 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 104 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 690 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 435 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 425 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 251 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 160 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 213 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 184 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 207 msecs
[], (-next v), 1000000 runs, 768 msecs
[], (-rest v), 1000000 runs, 326 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 679 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 781 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 672 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 965 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 403 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 20 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 267 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 675 msecs
[], (list 1 2 3 4 5), 1000000 runs, 639 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 2422 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 1725 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 1620 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 3240 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 2525 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 2980 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 453 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 549 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 265 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 1695 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 276 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 252 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 2831 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 373 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 276 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 515 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 320 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 355 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 322 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 297 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 416 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 360 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 331 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 894 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 732 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 1027 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 699 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 589 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 330 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 523 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 307 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 530 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 295 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 574 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 291 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 280 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 9 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 251 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 253 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 322 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 336 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 373 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 626 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 266 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 244 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 267 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 340 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 128 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 111 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 361 msecs
[coll pmap], (:f0 coll), 1000000 runs, 385 msecs
[coll pmap], (get coll :f0), 1000000 runs, 370 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 324 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 364 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 3598 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 657 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 565 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 421 msecs

transient map, conj! 100000 items
"Elapsed time: 539 msecs"


;;; set ops
[], #{}, 1000000 runs, 217 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 587 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 477 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 304 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 267 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 289 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 21 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 85 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 1060 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 77 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 369 msecs
;;; second run
[r r], (last r), 1 runs, 94 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 233 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 473 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 1233 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 688 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 53 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 52 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 177 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1298 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 57 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 569 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 67 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 82 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 134 msecs

0002 patch
==========

Benchmarking with SpiderMonkey
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 645 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 95 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 557 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 2 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 460 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 18 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 32 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 36 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 613 msecs
[coll "foobar"], (seq coll), 1000000 runs, 1658 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 834 msecs
[coll "foobar"], (first coll), 1000000 runs, 1934 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 219 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 1371 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 444 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 351 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 125 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 138 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 97 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 109 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 80 msecs
[], (list), 1000000 runs, 10 msecs
[], (list 1 2 3), 1000000 runs, 1387 msecs

;;; vector ops
[], [], 1000000 runs, 10 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 316 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0x57b33c29 "cljs.tagged_literals.JSValue@57b33c29"])), 1000000 runs, 732 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 281 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 484 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 112 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 162 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 194 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 125 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 756 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 606 msecs
[coll []], (-conj coll 1), 1000000 runs, 515 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 648 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 422 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 566 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 89 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 154 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 89 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 631 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 450 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 547 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 589 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 204 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 177 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 143 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 141 msecs
[], (-next v), 1000000 runs, 529 msecs
[], (-rest v), 1000000 runs, 236 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 924 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 633 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 610 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 1138 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 545 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 121 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 281 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 597 msecs
[], (list 1 2 3 4 5), 1000000 runs, 560 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 2573 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 1927 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 6163 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 3149 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 1883 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 659 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 611 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 556 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 368 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 1707 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 280 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 266 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 2862 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 356 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 391 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 439 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 363 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 321 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 405 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 328 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 444 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 330 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 353 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 1427 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 589 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 1087 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 674 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 719 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 287 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 841 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 327 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 625 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 294 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 630 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 314 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 312 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 10 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 269 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 268 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 309 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 440 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 404 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 756 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 290 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 326 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 279 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 338 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 138 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 177 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 385 msecs
[coll pmap], (:f0 coll), 1000000 runs, 411 msecs
[coll pmap], (get coll :f0), 1000000 runs, 439 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 336 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 457 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 4330 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 831 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 490 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 474 msecs

transient map, conj! 100000 items
"Elapsed time: 565 msecs"


;;; set ops
[], #{}, 1000000 runs, 225 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 711 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 608 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 353 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 322 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 335 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 22 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 99 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 1538 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 37 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 348 msecs
;;; second run
[r r], (last r), 1 runs, 71 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 433 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 287 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 1191 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 831 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 52 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 81 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 207 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1375 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 73 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 429 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 51 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 73 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 133 msecs
Comment by David Nolen [ 19/Jul/15 11:06 AM ]

Thanks will review.

Comment by David Nolen [ 20/Jul/15 2:33 PM ]

This ticket should probably be updated with the latest equiv changes in Clojure master no?

Comment by Michał Marczyk [ 20/Jul/15 2:49 PM ]

Right, will do (plus a rebase on top of current master while I'm at it).

Comment by Michał Marczyk [ 20/Jul/15 6:43 PM ]

New 0003 patch superseding the previous ones attached.

See some new benchmark results below. There are some apparent substantial speedups where I would expect them, there's the somewhat expected slowdown for transient with small vectors.

Freak result: most large vector ops stay around their original spots as expected, except for reduce conj [] over a long range, which becomes weirdly slow. This I find hard to explain, particularly since ranges are used in other benchmarks as well, and those behave sensibly.

I tried compiling the benchmark suite with :optimizations :simple to see if the freak result was something obvious maybe. Oddly enough, all/most timings are significantly better under :simple. Am I missing something obvious here…?

1. master:

Benchmarking with SpiderMonkey
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 506 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 70 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 554 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 3 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 313 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 15 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 19 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 33 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 401 msecs
[coll "foobar"], (seq coll), 1000000 runs, 1202 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 563 msecs
[coll "foobar"], (first coll), 1000000 runs, 1307 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 161 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 949 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 379 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 1025 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 59 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 88 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 67 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 80 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 62 msecs
[], (list), 1000000 runs, 10 msecs
[], (list 1 2 3), 1000000 runs, 1132 msecs

;;; vector ops
[], [], 1000000 runs, 10 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 495 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0x56b66a26 "cljs.tagged_literals.JSValue@56b66a26"])), 1000000 runs, 547 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 435 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 120 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 197 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 95 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 199 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 209 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 893 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 842 msecs
[coll []], (-conj coll 1), 1000000 runs, 765 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 854 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 631 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 413 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 668 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 163 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 89 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 497 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 319 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 316 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 172 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 240 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 128 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 80 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 105 msecs
[], (-next v), 1000000 runs, 460 msecs
[], (-rest v), 1000000 runs, 166 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 746 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 557 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 437 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 820 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 308 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 20 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 250 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 471 msecs
[], (list 1 2 3 4 5), 1000000 runs, 410 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 1898 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 1506 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 954 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 2495 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 1864 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 2799 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 2367 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 465 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 268 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 1228 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 251 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 270 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 3502 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 330 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 294 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 528 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 282 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 333 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 318 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 286 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 409 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 341 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 353 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 878 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 589 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 972 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 582 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 850 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 269 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 793 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 269 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 596 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 311 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 586 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 321 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 280 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 10 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 254 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 250 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 288 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 322 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 305 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 537 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 257 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 250 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 238 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 338 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 123 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 114 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 342 msecs
[coll pmap], (:f0 coll), 1000000 runs, 368 msecs
[coll pmap], (get coll :f0), 1000000 runs, 356 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 274 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 290 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 3028 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 641 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 412 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 411 msecs

transient map, conj! 100000 items
"Elapsed time: 505 msecs"


;;; set ops
[], #{}, 1000000 runs, 215 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 460 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 516 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 293 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 269 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 290 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 18 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 77 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 957 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 42 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 310 msecs
;;; second run
[r r], (last r), 1 runs, 71 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 234 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 416 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 981 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 699 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 50 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 52 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 184 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1278 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 46 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 333 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 216 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 71 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 142 msecs

2. 0003 patch:

Benchmarking with SpiderMonkey
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 480 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 71 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 476 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 3 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 621 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 28 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 30 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 54 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 542 msecs
[coll "foobar"], (seq coll), 1000000 runs, 1209 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 564 msecs
[coll "foobar"], (first coll), 1000000 runs, 1257 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 140 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 913 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 424 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 170 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 58 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 89 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 69 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 80 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 61 msecs
[], (list), 1000000 runs, 10 msecs
[], (list 1 2 3), 1000000 runs, 1142 msecs

;;; vector ops
[], [], 1000000 runs, 10 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 272 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0x3ff26c9 "cljs.tagged_literals.JSValue@3ff26c9"])), 1000000 runs, 585 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 240 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 273 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 101 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 102 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 102 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 38 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 429 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 392 msecs
[coll []], (-conj coll 1), 1000000 runs, 368 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 395 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 364 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 383 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 75 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 142 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 79 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 395 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 408 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 383 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 406 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 269 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 131 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 80 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 104 msecs
[], (-next v), 1000000 runs, 461 msecs
[], (-rest v), 1000000 runs, 171 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 592 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 562 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 467 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 830 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 426 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 15 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 265 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 580 msecs
[], (list 1 2 3 4 5), 1000000 runs, 386 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 1885 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 1362 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 4564 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 2536 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 1940 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 1948 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 452 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 484 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 264 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 1540 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 294 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 251 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 3150 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 378 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 278 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 507 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 288 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 339 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 324 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 301 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 533 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 355 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 309 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 757 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 514 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 844 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 622 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 765 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 271 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 521 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 276 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 515 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 314 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 534 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 324 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 327 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 10 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 290 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 254 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 301 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 347 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 365 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 496 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 242 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 254 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 262 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 319 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 128 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 124 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 368 msecs
[coll pmap], (:f0 coll), 1000000 runs, 446 msecs
[coll pmap], (get coll :f0), 1000000 runs, 511 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 328 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 319 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 4954 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 963 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 425 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 421 msecs

transient map, conj! 100000 items
"Elapsed time: 531 msecs"


;;; set ops
[], #{}, 1000000 runs, 230 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 679 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 605 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 295 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 273 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 321 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 22 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 73 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 934 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 33 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 310 msecs
;;; second run
[r r], (last r), 1 runs, 60 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 230 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 400 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 865 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 627 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 49 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 55 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 197 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1296 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 48 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 502 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 50 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 434 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 132 msecs
Comment by David Nolen [ 20/Jul/15 10:35 PM ]

Michal it might be a GC thing? Not sure. These tests need to be run on more engines, kinda wish we had something a bit more visual by now

Comment by Michał Marczyk [ 20/Jul/15 11:32 PM ]

Indeed… I got the V8 situation sorted in the meantime and benchmarked master vs 0003 with a fresh build; I thought the results were pretty encouraging, particularly the 2x speedup for "small vector conj".

1. master:

Benchmarking with V8
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 63 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 24 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 21 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 14 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 14 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 6 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 12 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 21 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 26 msecs
[coll "foobar"], (seq coll), 1000000 runs, 31 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 39 msecs
[coll "foobar"], (first coll), 1000000 runs, 59 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 37 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 139 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 26 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 61 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 20 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 16 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 13 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 10 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 11 msecs
[], (list), 1000000 runs, 5 msecs
[], (list 1 2 3), 1000000 runs, 67 msecs

;;; vector ops
[], [], 1000000 runs, 4 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 71 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0x158e6fc2 "cljs.tagged_literals.JSValue@158e6fc2"])), 1000000 runs, 56 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 83 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 28 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 23 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 25 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 22 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 27 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 64 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 60 msecs
[coll []], (-conj coll 1), 1000000 runs, 53 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 54 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 53 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 26 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 25 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 19 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 16 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 24 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 22 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 26 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 56 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 27 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 64 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 23 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 14 msecs
[], (-next v), 1000000 runs, 32 msecs
[], (-rest v), 1000000 runs, 33 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 41 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 36 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 327 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 974 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 74 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 16 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 28 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 61 msecs
[], (list 1 2 3 4 5), 1000000 runs, 146 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 121 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 809 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 141 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 201 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 483 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 290 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 295 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 271 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 27 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 711 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 23 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 24 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 1284 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 66 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 43 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 72 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 52 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 56 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 79 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 57 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 87 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 61 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 70 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 142 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 91 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 171 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 99 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 106 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 34 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 84 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 32 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 82 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 40 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 119 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 47 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 70 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 9 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 36 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 29 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 60 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 69 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 47 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 257 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 13 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 24 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 13 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 80 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 75 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 91 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 83 msecs
[coll pmap], (:f0 coll), 1000000 runs, 64 msecs
[coll pmap], (get coll :f0), 1000000 runs, 56 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 45 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 78 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 224 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 405 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 83 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 155 msecs

transient map, conj! 100000 items
"Elapsed time: 48 msecs"


;;; set ops
[], #{}, 1000000 runs, 5 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 355 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 243 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 48 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 38 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 54 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 24 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 23 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 654 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 42 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 319 msecs
;;; second run
[r r], (last r), 1 runs, 87 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 246 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 163 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 134 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 22 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 85 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 105 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 359 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1413 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 80 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 134 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 8 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 30 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 95 msecs

2. 0003:

Benchmarking with V8
[x 1], (identity x), 1000000 runs, 0 msecs
;; symbol construction
[], (symbol (quote foo)), 1000000 runs, 51 msecs

;; array-reduce & ci-reduce
[coll (seq arr)], (ci-reduce coll + 0), 1 runs, 23 msecs
[coll (seq arr)], (ci-reduce coll sum 0), 1 runs, 19 msecs
[coll arr], (array-reduce coll + 0), 1 runs, 13 msecs
[coll arr], (array-reduce coll sum 0), 1 runs, 11 msecs
;;; instance?
[coll []], (instance? PersistentVector coll), 1000000 runs, 6 msecs
;;; satisfies?
[coll (list 1 2 3)], (satisfies? ISeq coll), 1000000 runs, 12 msecs
[coll [1 2 3]], (satisfies? ISeq coll), 1000000 runs, 22 msecs

;;; array & string ops
[coll (array 1 2 3)], (seq coll), 1000000 runs, 27 msecs
[coll "foobar"], (seq coll), 1000000 runs, 39 msecs
[coll (array 1 2 3)], (first coll), 1000000 runs, 34 msecs
[coll "foobar"], (first coll), 1000000 runs, 44 msecs
[coll (array 1 2 3)], (nth coll 2), 1000000 runs, 35 msecs
[coll "foobar"], (nth coll 2), 1000000 runs, 137 msecs

;;; cloning & specify
[coll [1 2 3]], (clone coll), 1000000 runs, 23 msecs
[coll [1 2 3]], (specify coll IFoo (foo [_] :bar)), 1000000 runs, 69 msecs
[coll (specify [1 2 3] IFoo (foo [_] :bar))], (foo coll), 1000000 runs, 20 msecs

;;; list ops
[coll (list 1 2 3)], (first coll), 1000000 runs, 16 msecs
[coll (list 1 2 3)], (-first coll), 1000000 runs, 13 msecs
[coll (list 1 2 3)], (rest coll), 1000000 runs, 10 msecs
[coll (list 1 2 3)], (-rest coll), 1000000 runs, 10 msecs
[], (list), 1000000 runs, 4 msecs
[], (list 1 2 3), 1000000 runs, 67 msecs

;;; vector ops
[], [], 1000000 runs, 4 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count [a b c]), 1000000 runs, 40 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vec #object[cljs.tagged_literals.JSValue 0x3e5ebdfe "cljs.tagged_literals.JSValue@3e5ebdfe"])), 1000000 runs, 55 msecs
[[a b c] (take 3 (repeatedly (fn* [] (rand-int 10))))], (-count (vector a b c)), 1000000 runs, 46 msecs
[coll [1 2 3]], (transient coll), 100000 runs, 31 msecs
[coll [1 2 3]], (nth coll 0), 1000000 runs, 16 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 16 msecs
[coll [1 2 3]], (-nth coll 0), 1000000 runs, 16 msecs
[coll [1 2 3]], (coll 0), 1000000 runs, 24 msecs
[coll [1 2 3]], (conj coll 4), 1000000 runs, 31 msecs
[coll [1 2 3]], (-conj coll 4), 1000000 runs, 29 msecs
[coll []], (-conj coll 1), 1000000 runs, 25 msecs
[coll [1]], (-conj coll 2), 1000000 runs, 22 msecs
[coll [1 2]], (-conj coll 3), 1000000 runs, 26 msecs
[coll [1 2 3]], (seq coll), 1000000 runs, 26 msecs
[coll [1 2 3]], (-seq coll), 1000000 runs, 26 msecs
[coll (seq [1 2 3])], (first coll), 1000000 runs, 28 msecs
[coll (seq [1 2 3])], (-first coll), 1000000 runs, 24 msecs
[coll (seq [1 2 3])], (rest coll), 1000000 runs, 30 msecs
[coll (seq [1 2 3])], (-rest coll), 1000000 runs, 26 msecs
[coll (seq [1 2 3])], (next coll), 1000000 runs, 29 msecs

;;; large vector ops
[], (reduce conj [] (range 40000)), 10 runs, 60 msecs
[coll (reduce conj [] (range (+ 32768 32)))], (conj coll :foo), 100000 runs, 32 msecs
[coll (reduce conj [] (range 40000))], (assoc coll 123 :foo), 100000 runs, 63 msecs
[coll (reduce conj [] (range (+ 32768 33)))], (pop coll), 100000 runs, 22 msecs

;;; chunked seqs
[], (-first v), 1000000 runs, 14 msecs
[], (-next v), 1000000 runs, 36 msecs
[], (-rest v), 1000000 runs, 33 msecs

;;; transients
transient vector, conj! 1000000 items
"Elapsed time: 44 msecs"


;;; vector equality
[a (into [] (range 1000000)) b (into [] (range 1000000))], (= a b), 1 runs, 37 msecs

;;; keyword compare
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed)))))], (.sort arr compare), 100 runs, 281 msecs
[arr (into-array (repeatedly 10000 (fn* [] (keyword (rand-nth seed) (rand-nth seed)))))], (.sort arr compare), 100 runs, 1025 msecs

;;; reduce lazy-seqs, vectors, ranges
[coll (take 100000 (iterate inc 0))], (reduce + 0 coll), 1 runs, 75 msecs
[coll (range 1000000)], (reduce + 0 coll), 1 runs, 17 msecs
[coll (into [] (range 1000000))], (reduce + 0 coll), 1 runs, 25 msecs

;; apply
[coll (into [] (range 1000000))], (apply + coll), 1 runs, 69 msecs
[], (list 1 2 3 4 5), 1000000 runs, 206 msecs
[xs (array-seq (array 1 2 3 4 5))], (apply list xs), 1000000 runs, 121 msecs
[xs (list 1 2 3 4 5)], (apply list xs), 1000000 runs, 757 msecs
[xs [1 2 3 4 5]], (apply list xs), 1000000 runs, 924 msecs
[f (fn [a b & more])], (apply f (range 32)), 1000000 runs, 184 msecs
[f (fn [a b c d e f g h i j & more])], (apply f (range 32)), 1000000 runs, 453 msecs

;; update-in
[coll {:foo 1} ks [:foo]], (update-in coll ks inc), 1000000 runs, 320 msecs
[coll (array-map :foo 1) ks [:foo]], (update-in coll ks inc), 1000000 runs, 301 msecs

;;; obj-map
[coll (obj-map)], (assoc coll :foo :bar), 1000000 runs, 267 msecs
[coll (obj-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 27 msecs
[coll (obj-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 727 msecs
[coll (obj-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 24 msecs
[coll (obj-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 25 msecs

;;; array-map
[], {[1] true, [2] true, [3] true}, 1000000 runs, 762 msecs
[coll (array-map)], (assoc coll :foo :bar), 1000000 runs, 66 msecs
[coll (array-map :foo :bar)], (-lookup coll :foo), 1000000 runs, 50 msecs
[coll (array-map :foo :bar)], (assoc coll :baz :woz), 1000000 runs, 74 msecs
[coll (array-map :foo :bar :baz :woz)], (-lookup coll :baz), 1000000 runs, 56 msecs
[coll (array-map :foo :bar :baz :woz :lol :rofl)], (-lookup coll :lol), 1000000 runs, 62 msecs

;;; array-map w/ symbols
[coll (array-map)], (assoc coll a b), 1000000 runs, 82 msecs
[coll (array-map a b)], (-lookup coll a), 1000000 runs, 61 msecs
[coll (array-map a b)], (assoc coll c d), 1000000 runs, 90 msecs
[coll (array-map a b c d)], (-lookup coll c), 1000000 runs, 65 msecs
[coll (array-map a b c d e f)], (-lookup coll e), 1000000 runs, 72 msecs

;;; array-map w/ inline symbols
[coll (array-map)], (assoc coll (quote foo) (quote bar)), 1000000 runs, 142 msecs
[coll (array-map (quote foo) (quote bar))], (-lookup coll (quote foo)), 1000000 runs, 92 msecs
[coll (array-map (quote foo) (quote bar))], (assoc coll (quote baz) (quote woz)), 1000000 runs, 163 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz))], (-lookup coll (quote baz)), 1000000 runs, 102 msecs
[coll (array-map (quote foo) (quote bar) (quote baz) (quote woz) (quote lol) (quote rofl))], (-lookup coll (quote lol)), 1000000 runs, 105 msecs

;;; map / record ops
[coll {:foo 1, :bar 2}], (get coll :foo), 1000000 runs, 35 msecs
[coll {(quote foo) 1, (quote bar) 2}], (get coll (quote foo)), 1000000 runs, 86 msecs
[coll {:foo 1, :bar 2}], (-lookup coll :foo nil), 1000000 runs, 31 msecs
[coll {(quote foo) 1, (quote bar) 2}], (-lookup coll (quote foo) nil), 1000000 runs, 80 msecs
[coll {:foo 1, :bar 2}], (:foo coll), 1000000 runs, 42 msecs
[coll {(quote foo) 1, (quote bar) 2}], ((quote foo) coll), 1000000 runs, 116 msecs
[coll {:foo 1, :bar 2}], (kw coll), 1000000 runs, 47 msecs
[coll {(quote foo) 1, (quote bar) 2}], (sym coll), 1000000 runs, 67 msecs
[coll {:foo 1, :bar 2}], (loop [i 0 m coll] (if (< i 100000) (recur (inc i) (assoc m :foo 2)) m)), 1 runs, 5 msecs
[coll (Foo. 1 2)], (:bar coll), 1000000 runs, 35 msecs
[coll (Foo. 1 2)], (-lookup coll :bar), 1000000 runs, 30 msecs
[coll (Foo. 1 2)], (assoc coll :bar 2), 1000000 runs, 52 msecs
[coll (Foo. 1 2)], (assoc coll :baz 3), 1000000 runs, 61 msecs
[coll (Foo. 1 2)], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :bar 2)) m)), 1 runs, 44 msecs

;;; zipmap
[m {:a 1, :b 2, :c 3}], (zipmap (keys m) (map inc (vals m))), 100000 runs, 230 msecs

;;; persistent hash maps
[key :f0], (hash key), 1000000 runs, 13 msecs
[key "f0"], (m3-hash-unencoded-chars key), 1000000 runs, 22 msecs
[key :unsynchronized-mutable], (hash key), 1000000 runs, 11 msecs
[coll hash-coll-test], (hash-coll coll), 100 runs, 70 msecs
[coll hash-coll-test], (hash-ordered-coll coll), 100 runs, 65 msecs
[coll hash-imap-test], (hash-imap coll), 100 runs, 73 msecs
[coll hash-imap-test], (hash-unordered-coll coll), 100 runs, 96 msecs
[coll pmap], (:f0 coll), 1000000 runs, 64 msecs
[coll pmap], (get coll :f0), 1000000 runs, 52 msecs
[coll pmap], (-lookup coll :f0 nil), 1000000 runs, 47 msecs
[coll pmap], (-lookup hash-imap-test :foo500 nil), 1000000 runs, 79 msecs
[coll pmap], (-lookup hash-imap-int-test 500 nil), 1000000 runs, 216 msecs
[coll pmap], (assoc coll :g0 32), 1000000 runs, 405 msecs
[coll pmap], (loop [i 0 m coll] (if (< i 1000000) (recur (inc i) (assoc m :a 1)) m)), 1 runs, 80 msecs
[coll cljs.core.PersistentHashMap.EMPTY], (assoc coll :f0 1), 1000000 runs, 156 msecs

transient map, conj! 100000 items
"Elapsed time: 53 msecs"


;;; set ops
[], #{}, 1000000 runs, 5 msecs
[], #{1 3 2}, 1000000 runs, 0 msecs
[v [1 2 3]], (set v), 1000000 runs, 515 msecs
[], (hash-set 1 2 3), 1000000 runs, 0 msecs
[coll #{1 3 2}], (conj coll 4), 1000000 runs, 266 msecs
[coll #{1 3 2}], (get coll 2), 1000000 runs, 50 msecs
[coll #{1 3 2}], (contains? coll 2), 1000000 runs, 38 msecs
[coll #{1 3 2}], (coll 2), 1000000 runs, 62 msecs

;;; seq ops
[coll (range 500000)], (reduce + coll), 1 runs, 23 msecs

;;; reader
[s "{:foo [1 2 3]}"], (reader/read-string s), 1000 runs, 30 msecs
[s big-str-data], (reader/read-string s), 1000 runs, 636 msecs

;;; range
[r (range 1000000)], (last r), 1 runs, 44 msecs

;;; lazy-seq
;;; first run
[r r], (last r), 1 runs, 322 msecs
;;; second run
[r r], (last r), 1 runs, 90 msecs

;;; comprehensions
[xs (range 512)], (last (for [x xs y xs] (+ x y))), 1 runs, 229 msecs
[xs (vec (range 512))], (last (for [x xs y xs] (+ x y))), 4 runs, 196 msecs
[a (Box. 0) xs (range 512)], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 133 msecs
[a (Box. 0) xs (vec (range 512))], (doseq [x xs y xs] (set! a -val (+ (.-val a) x))), 4 runs, 23 msecs

;; reducers
[xs (into [] (range 1000000))], (r/reduce + (r/map inc (r/map inc (r/map inc xs)))), 1 runs, 85 msecs
;; transducers
[xs (into [] (range 1000000))], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 108 msecs
;; primitive array reduce 1000000 many ops
[xs (into-array (range 1000000))], (-> xs (.map inc) (.map inc) (.map inc) (.reduce (fn [a b] (+ a b)) 0)), 1 runs, 349 msecs
;; reduce range 1000000 many ops
[xs (range 1000000)], (reduce + 0 (map inc (map inc (map inc xs)))), 1 runs, 1387 msecs
;; transduce range 1000000 many ops 
[xs (range 1000000)], (transduce (comp (map inc) (map inc) (map inc)) + 0 xs), 1 runs, 79 msecs


;; multimethods
[], (simple-multi :foo), 1000000 runs, 122 msecs


;; higher-order variadic function calls
[f array], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 8 msecs
[f vector], (f 1 2 3 4 5 6 7 8 9 0), 100000 runs, 154 msecs
[], (= 1 1 1 1 1 1 1 1 1 0), 100000 runs, 94 msecs
Comment by Michał Marczyk [ 20/Jul/15 11:35 PM ]

(No rebase this time, as 0003 still applies cleanly and all tests pass.)

Comment by David Nolen [ 10/Nov/15 8:41 AM ]

De-prioritized. We need to be able to prove the issues around the proposed JVM approach doesn't also appear under popular JS engines.





[CLJS-1295] Improve doc for instance Created: 01/Jun/15  Updated: 01/Jun/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Julien Eluard Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1295.patch    

 Description   

Doc for instance? does not reflect argument names.






[CLJS-1251] Missing semicolons when emitting deftype and defrecord Created: 07/May/15  Updated: 07/May/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Antonin Hildebrand Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_1251.patch    

 Description   

Emitted code for deftype and defrecord has to separate the var assignment from body content by a semicolon (do not rely on automatic javascript semicolon insertion).

The bad case:
If body has the first statement wrapped in (...), javascript will treat it as a function call on the constructor definition.






[CLJS-1185] Support preambles when our target is node.js and we are compiler a main file Created: 02/Apr/15  Updated: 02/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Ivan Willig Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1185.patch    




[CLJS-1009] Allow deps.cljs to declare a foreign lib as remote Created: 05/Feb/15  Updated: 21/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

When using things like the Google Maps JS API [1] the Javascript that is required can't be bundled inside a jar as it depends on the used API key.

To be able to provide externs for those kind of libraries there should be a way to declare them as "remote" in deps.cljs.

[1] https://developers.google.com/maps/documentation/javascript/tutorial






[CLJS-924] Better error message for mistaken use of 'def' Created: 24/Dec/14  Updated: 20/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Alex Dowad Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-Better-error-message-if-def-is-mistakenly-substitute.patch     Text File CLJS-924.patch    
Patch: Code

 Description   

ClojureScript shares what is IMHO one of the biggest weaknesses of the current JVM Clojure implementation: those (in)famous stack traces going down into the innards of the compiler if you get your syntax wrong. An easy mistake for noobs is to use 'def' in place of 'defn'; this patch makes that mistake a lot less painful to debug.

Feedback please!



 Comments   
Comment by Mike Fikes [ 05/Feb/16 8:19 PM ]

Patch no longer applies.

Comment by Mike Fikes [ 20/Feb/16 9:49 PM ]

Revised patch CLJS-924.patch applies to master.

(Based on Alex Dowad's original patch. Both Alex and I have signed the CA.)





[CLJS-884] with-redefs don't restores previous values when used inside go block Created: 09/Nov/14  Updated: 09/Nov/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Vladimir Iakovlev Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None
Environment:

clojure 1.6, clojurescript 0.0-2371, core.async 0.1.346.0-17112a-alpha


Attachments: Text File cljs_884.patch    

 Description   

For example I have code and test:

(defn test-fn [] :original)

(deftest ^:async test-with-redefs-async
  (go (is (= (test-fn) :original))
      (with-redefs [test-fn (fn [] :mocked)]
        (is (= (test-fn) :mocked)))
      (is (= (test-fn) :original))
      (done)))

And test failed in last `is`:

FAIL in (test-with-redefs-async) (:)
expected: (= (test-fn) :original)
  actual: (not (= :mocked :original))


 Comments   
Comment by Vladimir Iakovlev [ 09/Nov/14 1:26 PM ]

I attached little patch with fix. With it `with-redefs` forced to use previous value for restoring bindings.

But I don't know how to add test for this issue, because it requires core.async. So I tested with:

(defn test-fn [] :original)

(deftest test-with-redefs-sync
  (is (= (test-fn) :original))
  (with-redefs [test-fn (fn [] :mocked)]
    (is (= (test-fn) :mocked)))
  (is (= (test-fn) :original)))

(deftest ^:async test-with-redefs-async
  (go (is (= (test-fn) :original))
      (with-redefs [test-fn (fn [] :mocked)]
        (is (= (test-fn) :mocked)))
      (is (= (test-fn) :original))
      (done)))




[CLJS-872] Ordered collections printed as if they were unordered at the REPL Created: 13/Oct/14  Updated: 14/Oct/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Michał Marczyk Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This is due to cljs.repl's read-then-print processing of string representations of return values that come back from the JS env. As of release 2371, the relevant code fragment lives here:

https://github.com/clojure/clojurescript/blob/r2371/src/clj/cljs/repl.clj#L156

A larger snippet to demonstrate this:

ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
{1 2, 3 4, 5 6, 7 8, 9 10, 11 12, 13 14}
ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}
ClojureScript:cljs.user> (seq (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18))
([1 2] [3 4] [5 6] [7 8] [9 10] [11 12] [13 14] [15 16] [17 18])
ClojureScript:cljs.user> (hash-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}

This issue seems to be the most likely cause of the problem described in this StackOverflow question. It would be nice to print ordered collections in the "expected" way to prevent user confusion.



 Comments   
Comment by David Nolen [ 14/Oct/14 5:23 AM ]

How is this handled in Clojure?

Comment by Michał Marczyk [ 14/Oct/14 7:40 AM ]

The built-in REPL simply prints string representations of values to *out* without attempting to read them back in first.

Comment by David Nolen [ 14/Oct/14 7:54 AM ]

Well the result of REPL evaluation is a string unlike Clojure, in order to get a proper print at the ClojureScript REPL it seems necessary to read back the result. I will say it's not clear to me array-map promises anything about order anyway.

Comment by Michał Marczyk [ 14/Oct/14 8:02 AM ]

It does – see http://clojure.org/data_structures, where it says

ArrayMaps
When doing code form manipulation it is often desirable to have a map which maintains key order. An array map is such a map - it is simply implemented as an array of key val key val... As such, it has linear lookup performance, and is only suitable for very small maps. It implements the full map interface. New ArrayMaps can be created with the array-map function. Note that an array map will only maintain sort order when un-'modified'. Subsequent assoc-ing will eventually cause it to 'become' a hash-map.

This snippet has been there for as long as I can remember; and this particular feature comes up in various online discussions from time to time. The docstrings for array-map (the core function) are unambiguous in their promise to construct array maps in both Clojure and ClojureScript.

As for the issue at hand, I do think it's a very minor one (hence the "Trivial" priority), but it is real – the representation printed at the REPL is out of line with the string returned from pr-str on the same value. In fact, one way to fix this would be to use pr-str representations computed on the CLJS side. (There may be some complications here, though, which we'd have to work out.)

Comment by David Nolen [ 14/Oct/14 8:07 AM ]

Thanks for pointing out the API promise. OK, yeah I don't really have a good idea for how do this but a patch that isn't too ugly is welcome





[CLJS-844] Optimize js->clj by switching to transients Created: 22/Aug/14  Updated: 09/Oct/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Darrick Wiebe Assignee: Darrick Wiebe
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File use-transducers-in-js-to-clj.patch     Text File use-transducers-in-js-to-clj.patch    

 Comments   
Comment by David Nolen [ 23/Aug/14 1:19 PM ]

Did you any benchmarks on other JS engines?

Comment by Darrick Wiebe [ 23/Aug/14 2:14 PM ]

No. My main concern was to check if there was any startup overhead that might offset the basic efficiency improvements for processing small collections. Using into with a transducer turned out to be faster in every scenario, significantly in most.

Comment by David Nolen [ 23/Aug/14 2:19 PM ]

It would be nice to see a jsperf of before and after on this ticket. Thanks.

Comment by Darrick Wiebe [ 23/Aug/14 2:23 PM ]

Is there a existing one that I can work from?

Comment by David Nolen [ 23/Aug/14 2:35 PM ]

There is not. I generally just make a simple project, create an advanced compiled artifact and copy and paste it into jsperf.

Comment by Darrick Wiebe [ 24/Aug/14 7:24 PM ]

Turns out reducing into a transient is considerably better than using a transducer (which was itself a little faster) for this.

http://jsperf.com/js-clj-transducer-test

The code is at:

https://gist.github.com/pangloss/591d77231fda460c2fbe

Let me know if you want me to prepare an updated patch.

Comment by David Nolen [ 25/Aug/14 7:34 AM ]

Thanks for putting this together. Yes please provide an updated patch.

Comment by Darrick Wiebe [ 26/Aug/14 11:19 AM ]

Not sure whether the convention is to comment that I've uploaded a new patch. Regardless, I uploaded it yesterday.

Comment by Marcin Kulik [ 07/Oct/15 1:46 PM ]

I have tested and benchmarked the patch on a big js objects (5MB+ json files) and I confirm that new-js->clj3 function is more than 2x faster. It runs now in the player on https://asciinema.org and all seems good so far.

Comment by David Nolen [ 08/Oct/15 2:33 PM ]

Marcin thanks for the feedback. Experience reports always help push tickets forward.

Darrick, the patch need to be rebased to master. Please remove all patches except the one that will be applied.

Comment by Rohit Aggarwal [ 08/Oct/15 3:06 PM ]

[ClojureScript beginner here. so do ignore this if I am mistaken]

The patch of 25/Aug uses `(aget x k)` instead of `(goog.object/get x k)` for getting the value of a key if x is an object. I believe it isn't the right way even though it works.

This contains why the latter is preferred over the former.

Comment by David Nolen [ 09/Oct/15 12:33 PM ]

Rohit good catch. Yes that should be changed.





[CLJS-633] Missing Java type hints in closure.clj Created: 22/Oct/13  Updated: 22/Oct/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Julien Eluard Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_ticket_633.patch    

 Description   

A number of reflection warnings are generated from closure.clj. Fixing those probably would not improved performance but it would be cleaner anyway.



 Comments   
Comment by Julien Eluard [ 22/Oct/13 8:03 AM ]

Attached patch.

There are a couple warnings left, similar to:
Reflection warning, cljs/closure.clj:232:1 - reference to field url can't be resolved.
They appear to be due to some unexpected protocol method name? It looks harmless.





[CLJS-555] CLONE - Implement ratios Created: 27/Jul/13  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Stuart Halloway Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None


 Description   

Clojure.java contains support for Ratio types. It would be nice to have them in Clojurescript as well, but as far as I can tell this would be new development (please comment if I'm wrong). That is, there is no implementation of Ratio types in GClosure so this feature would need to be implemented from the ground up. In additional to the Ratio type, the following corresponding functions would also need implementations:

  • `ratio?`
  • `numerator`
  • `denominator`
  • `rationalize`

Plus the ratio type would need to be rolled into the existing mathematical frameworkings.

Imported from github issue #66



 Comments   
Comment by David Nolen [ 02/Dec/14 6:14 AM ]

Lower priority, unsolvable without numerics overhaul.





[CLJS-507] Persistent Data Structure Benchmark Created: 20/May/13  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Trivial
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Put together an easy to run series of persistent data structure benchmarks that can be easily run. For example we would like to submit to this Mozilla ticket http://bugzilla.mozilla.org/show_bug.cgi?id=874174






[CLJS-450] (ns) within (do) inconsistent with Clojure behaviour Created: 27/Dec/12  Updated: 21/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Stuart Campbell Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

An (ns) within a (do) doesn't quite work as expected at the REPL:

ClojureScript:cljs.user> (do (ns foo) (def x 42))   
nil
ClojureScript:foo> x
nil
ClojureScript:cljs.user> cljs.user/x
42

The Clojure equivalent:

user=> (do (ns foo) (def x 42))
#'foo/x
foo=> x
42


 Comments   
Comment by David Nolen [ 05/Jan/13 2:05 PM ]

Looks like we need to do something similar to what is done in Clojure with top level do - http://github.com/frenchy64/typed-clojure/pull/4





[CLJS-324] cljs.core/format Created: 24/Jun/12  Updated: 11/Mar/15

Status: Reopened
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Gary Fredericks Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File 0001-CLJS-324-implement-cljs.core-format-as-wrapper-for-g.patch     File goog.string.format-0.0-1913.tgz    

 Description   

Implement cljs.core/format. Make sure there is nothing in gclosure for this. I suppose we should try to emulate the jvm version as much as that makes sense?



 Comments   
Comment by Michał Marczyk [ 28/Jun/12 11:29 AM ]

GClosure does actually include a string formatter – goog.string.format. Note that that's both a non-ctor function name and the GClosure "namespace" name, so in order to use it one must require goog.string.format on top of gstring and say gstring/format (or perhaps leave out the gstring require spec and use goog.string/format – not tested, but should work).

The patch to introduce format and printf as wrappers for goog.string.format is naturally extremely simple, so here it is. Note that this particular patch must be applied on top of CLJS-328.

I have no idea how goog.string.format compares to the JVM's String/format (basic number formatting seems to work as it should in sprintf-like functions, but other than that I haven't tested it much).

Comment by David Nolen [ 29/Jun/12 10:44 AM ]

The tests fail for me with this patch applied.

Comment by David Nolen [ 29/Jun/12 11:07 AM ]

fixed, http://github.com/clojure/clojurescript/commit/8f518760a3df8b351208e97bb70270856623bb0a

Comment by David Nolen [ 11/Sep/13 5:05 PM ]

Backing this one out, goog.string.format defies advanced optimization and it provides few of the capabilities of Clojure's format - which does a lot because of java.util.Formatter. Apologies for the churn, but this is a simple thing for people to stub in themselves for the little bit of functionality it actually delivers.

Comment by Lars Bohl [ 12/Oct/13 6:33 AM ]

Uploading a slighly modified version lein-cljsbuild's "advanced" demo, to demonstrate that using goog.string.format produces a runtime error with clojurescript 0.0.1913. Run "lein ring server" and navigate to http://localhost:3000/

The code in hello.cljs shows that goog.string.toTitleCase works, but not goog.string.format.

Comment by Julien Eluard [ 12/Oct/13 6:43 AM ]

It looks like you are not requiring correctly format. See a working example here.

Comment by Lars Bohl [ 12/Oct/13 6:58 AM ]

Julent, thanks! It needs another [goog.string.format] after [goog.string :as gstring] before you can use gstring/format. hello.cljs now looks like this, and throws no exceptions: https://www.refheap.com/19693





Generated at Wed May 25 23:45:27 CDT 2016 using JIRA 4.4#649-r158309.