On Nov 10, 2010, at 9:05 PM, Sean Corfield wrote:

> On Wed, Nov 10, 2010 at 11:37 AM, Gary Poster <gary.pos...@gmail.com> wrote:
>> In my opinion, its promise is that it reverses anything that supports the 
>> minimal seq interface.  Its implementation can be pluggable via protocols
> 
> Hmm, don't protocols have some overhead? Switching an implementation
> from a direct, possibly inlined, function to one that uses protocols
> is going to slow it down, surely?

The answer, as I expected, is "a small bit."  

I didn't get around to giving criterium 
(https://github.com/hugoduncan/criterium) a whirl for more careful statistics, 
but after a first run (JIT optimization doing its thing, I assume), these are 
some mins after a few runs, and representative.  rseq is rseq, seq-reverse is a 
protocol-based reverse function copying the implementation of the built-ins, 
and s is a vector (vec (range 1000)).

1:49 user=> (time (dotimes [_ 10000] (rseq s)))
"Elapsed time: 1.761 msecs"
nil
1:50 user=> (time (dotimes [_ 10000] (seq-reverse s)))
"Elapsed time: 2.167 msecs"
nil

So, back-of-the-napkin, adding the protocol adds about 25% overhead.

For comparison, with the built-in reverse and no O(1) performance, you get 
348.634 msecs.  Even if the vector is (random example) 30 elements, you get 
11.559 msecs.

Also, the protocol cost pretty much disappears when you work with a list (that 
is, comparing (seq-reverse l) and (reverse l) where l is a list of 30 or 1000 
elements.

In sum, from a performance perspective, implementing these with protocols 
doesn't hurt reverse at all, and even only hurts rseq a tiny bit.

Gary


...
To dupe, this is my really-fast definition of seq-reverse, based on the source 
of rseq and reverse.  I didn't take the time to see if the type hints were 
still useful in the protocol version; and I added the clojure.lang.Reversable 
thing as an idle gesture, since that might be more appropriate for a real story.

=> (defprotocol SEQ
  (seq-reverse [coll]))

=> (extend-type clojure.lang.IPersistentVector
  (seq-reverse [^clojure.lang.Reversible rev] (. rev (rseq))))

=> (extend-type java.lang.Object
  SEQ
  (seq-reverse [coll] (reduce conj () coll)))

=> (extend-type clojure.lang.Reversible
  SEQ
  (seq-reverse [^clojure.lang.Reversible rev] (. rev (rseq))))


-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to