Details
-
Type:
Enhancement
-
Status:
Closed
-
Priority:
Major
-
Resolution: Duplicate
-
Affects Version/s: Release 1.5
-
Fix Version/s: Release 1.7
-
Component/s: None
-
Labels:
-
Approval:Incomplete
Description
(vec coll) and (into [] coll) do exactly the same thing. However, due to into using transients, it is substantially faster. On my machine:
(time (dotimes [_ 100] (vec (range 100000))))
"Elapsed time: 732.56 msecs"
(time (dotimes [_ 100] (into [] (range 100000))))
"Elapsed time: 491.411 msecs"
This is consistently repeatable.
Since vec's sole purpose is to transform collections into vectors, it should do so at the maximum speed available.
Activity
Luke VanderHart
made changes -
Field | Original Value | New Value |
---|---|---|
Description |
{{(vec coll)}} and {{(into [] coll)}} do exactly the same thing. However, due to {{into}}s use of transients, it is substantially faster. On my machine:
(time (dotimes [_ 100] (vec (range 100000)))) "Elapsed time: 732.56 msecs" (time (dotimes [_ 100] (into [] (range 100000)))) "Elapsed time: 491.411 msecs" This is consistently repeatable. Since {{vec}}'s sole purpose is to transform collections into vectors, it should do so at the maximum speed available. |
{{(vec coll)}} and {{(into [] coll)}} do exactly the same thing. However, due to {{into}} using transients, it is substantially faster. On my machine:
(time (dotimes [_ 100] (vec (range 100000)))) "Elapsed time: 732.56 msecs" (time (dotimes [_ 100] (into [] (range 100000)))) "Elapsed time: 491.411 msecs" This is consistently repeatable. Since {{vec}}'s sole purpose is to transform collections into vectors, it should do so at the maximum speed available. |
Alex Miller
made changes -
Labels | performance |
Alex Miller
made changes -
Priority | Trivial [ 5 ] | Major [ 3 ] |
Approval | Triaged [ 10120 ] |
Rich Hickey
made changes -
Approval | Triaged [ 10120 ] | Vetted [ 10003 ] |
Fix Version/s | Release 1.7 [ 10250 ] |
Alex Miller
made changes -
Issue Type | Defect [ 1 ] | Enhancement [ 4 ] |
Alex Miller
made changes -
Approval | Vetted [ 10003 ] | Incomplete [ 10006 ] |
Alex Miller
made changes -
Status | Open [ 1 ] | Closed [ 6 ] |
Resolution | Duplicate [ 3 ] |
I am pretty sure that Clojure 1.5.1 also uses transient vectors for (vec (range n)) (probably also some earlier versions of Clojure, too).
Look at vec in core.clj. It checks whether its arg is a java.util.Collection, which lazy seqs are, so calls (clojure.lang.LazilyPersistentVector/create coll).
LazilyPersistentVector's create method checks whether its argument is an ISeq, which lazy seqs are, so it calls PersistentVector.create(RT.seq(coll)).
All 3 of PersistentVector's create() methods use transient vectors to build up the result.
I suspect the difference in run times are not because of transients or not, but because of the way into uses reduce, and perhaps may also have something to do with the perhaps-unnecessary call to RT.seq in LazilyPersistentVector's create method (in this case, at least – it is likely needed for other types of arguments).