On Jul 8, 4:57 pm, Frantisek Sodomka <[email protected]> wrote:
> So far it seems that vectors win in Clojure:
>
> (timings 3e5
> (let [v (vector 1 2 3) a (nth v 0) b (nth v 1) c (nth v 2)] (+ a b
> c))
> (let [lst (list 1 2 3) a (nth lst 0) b (nth lst 1) c (nth lst 2)] (+
> a b c)))
>
> =>
> 680.63 ms 83.6% 1.2x (let [v (vector 1 2 3) a (nth v 0) b (nth
> v 1) c (nth v 2)] (+ a b c))
> 813.79 ms 100.0% 1.0x (let [lst (list 1 2 3) a (nth lst 0) b
> (nth lst 1) c (nth lst 2)] (+ a b c))
>
> Frantisek
>
> On Jul 8, 7:29 pm, John Harrop <[email protected]> wrote:
>
> > Interesting. How are these timings affected if you add in the time taken to
> > pack the list or vector in the first place, though? I have the feeling it
> > may be slightly cheaper to unpack a vector, but noticeably cheaper to pack a
> > list...
>
>
I did some playing and it seems that the x-factor is really whether or
not the array access function is in-lined into the code. I made a few
tweaks to the source code so that the destructuring bind is able to
rewrite the code with the 2-ary version and avoid rebinding overhead.
I'll post it in reply to this.
Here are some results I collected:
(I like your 'timings' macro, by the way).
(let [v [1 2 3] lst '(1 2 3)]
(timings 1e7
(let [[a b c] v] a b c)
(let [[a b c] #^{:length 3} v] a b c)
(let [[a b c] #^{:tag :vector :length 3} v] a b c)
(let [[a b c] #^{:length 3} [1 2 3]] a b c)
(let [a (v 0) b (v 1) c (v 2)] a b c)
(let [a (nth v 0) b (nth v 1) c (nth v 2)] a b c)
(let [a (first v) b (second v) c (first (rest (rest v)))] a b c)
(let [x (first v) r1 (rest v) y (first r1) r2 (rest r1) z (first
r2)] x y z)
(let [[a b c] lst] a b c)
;; (let [a (lst 0) b (lst 1) c (lst 2)] [a b c])
(let [a (nth lst 0) b (nth lst 1) c (nth lst 2)] a b c)
(let [a (first lst) b (second lst) c (first (rest (rest lst)))] a
b c)
(let [x (first lst) r1 (rest lst) y (first r1) r2 (rest r1) z
(first r2)] x y z)))
---
no inlining of 3-ary version (inlines 2ary version as normal),
rewriting to 2-ary version dependant on :length :tag metadata and
4650.19 ms 34.2% 2.9x (let [[a b c] v] a b c) ;;nothing
3675.41 ms 27.0% 3.7x (let [[a b c] v] a b c) ;;length
3414.78 ms 25.1% 4.0x (let [[a b c] v] a b c) ;; tag length
13606.68 ms 100.0% 1.0x (let [[a b c] [1 2 3]] a b c)
3459.74 ms 25.4% 3.9x (let [a (v 0) b (v 1) c (v 2)] a b c)
3551.73 ms 26.1% 3.8x (let [a (nth v 0) b (nth v 1) c (nth v 2)]
a b c)
9810.52 ms 72.1% 1.4x (let [a (first v) b (second v) c (first
(rest (rest v)))] a b c)
9234.34 ms 67.9% 1.5x (let [x (first v) r1 (rest v) y (first r1)
r2 (rest r1) z (first r2)] x y z)
9519.99 ms 70.0% 1.4x (let [[a b c] lst] a b c)
7131.29 ms 52.4% 1.9x (let [a (nth lst 0) b (nth lst 1) c (nth
lst 2)] a b c)
7665.99 ms 56.3% 1.8x (let [a (first lst) b (second lst) c
(first (rest (rest lst)))] a b c)
7490.44 ms 55.0% 1.8x (let [x (first lst) r1 (rest lst) y (first
r1) r2 (rest r1) z (first r2)] x y z)
---
inlining 3ary version, rewriting dependant on :length and :tag.
3230.53 ms 24.6% 4.1x (let [[a b c] v] a b c) ;;nothing
3557.94 ms 27.1% 3.7x (let [[a b c] v] a b c) ;;length
3287.01 ms 25.1% 4.0x (let [[a b c] v] a b c) ;;tag +length
13116.50 ms 100.0% 1.0x (let [[a b c] [1 2 3]] a b c)
3287.39 ms 25.1% 4.0x (let [a (v 0) b (v 1) c (v 2)] a b c)
3615.61 ms 27.6% 3.6x (let [a (nth v 0) b (nth v 1) c (nth v 2)]
a b c)
10634.64 ms 81.1% 1.2x (let [a (first v) b (second v) c (first
(rest (rest v)))] a b c)
10147.02 ms 77.4% 1.3x (let [x (first v) r1 (rest v) y (first r1)
r2 (rest r1) z (first r2)] x y z)
8476.63 ms 64.6% 1.5x (let [[a b c] lst] a b c)
7106.42 ms 54.2% 1.8x (let [a (nth lst 0) b (nth lst 1) c (nth
lst 2)] a b c)
8172.17 ms 62.3% 1.6x (let [a (first lst) b (second lst) c
(first (rest (rest lst)))] a b c)
8031.60 ms 61.2% 1.6x (let [x (first lst) r1 (rest lst) y (first
r1) r2 (rest r1) z (first r2)] x y z)
I'll post the rather small tweaks in a response to this post. Please
note that i was playing with a (month old) alpha 1.1 version of
clojure.core, so I am not sure what the differences would be between
it and a current version. I think the most interesting part is that
you can get pretty much the same effect by just telling it to inline
the 3ary version of nth. (Although it is a multi function, so it seems
there is still some sort of funcall overhead).
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---