On Thu, Jun 24, 2010 at 5:17 PM, David Nolen <dnolen.li...@gmail.com> wrote:

> On Thu, Jun 24, 2010 at 5:08 PM, Heinz N. Gies <he...@licenser.net> wrote:
>
>> So out of curiosity I did some benchmarking of the new equal branch and
>> wanted to see how much I can get out of clojure if I push the limits. Now
>> that said I know equal isn't done yet but I figured it won't hurt. Bad news
>> first, despite all my attempts clojure was still slower then optimized scala
>> code (of cause this is a purely hypothetical benchmark and that scala is way
>> closer to java gives it a huge advantage when it coms to that).
>>
>> The benchmark I did was the fannkuchen-redux benchmark the code I came up
>> with was the following:
>>
>>
>> http://github.com/Licenser/clj-shootout/blob/master/fannkuchen/src/profile/fannkuchen.clj
>>
>> the scala version I used is from the alioth shootout:
>>
>>
>> http://github.com/Licenser/clj-shootout/blob/master/fannkuchen/scala/fannkuchen.scala
>>
>> For the clojure version, I tried to get rid of anything that isn't very
>> close to java. All data ist stored in mutable arrays, all in all I use three
>> and no extra data is allocated or tossed away for this. I tried to make
>> everything I could to a macro (removing overhead for function calls), also I
>> tried to use unchecked and primitive math wherever possible. The code is not
>> pretty and certainly not idiomatic but it is somewhat fast, I managed to get
>> things to a point where my clojure version took only 3.5 times longer then
>> the scala version (I say only since the most idiomatic version was beyond
>> compare so it was just beautiful!).
>>
>> After this I did some profiling - eevar will love me for that - and I
>> noticed one thing that stood out. intCast is called a gazillion times (in a
>> run of about 4 seconds it was called ca. 150 million times) that IS a lot
>> and it took some time (more then 10% of the over all execution time).  That
>> stroke me as odd, so I did some diging and found an interesting point:
>>
>> Java arrays use int's as index - which since long is the primitive causes
>> every single array access to be typecast via the intCast(long) call which is
>> expensive since it does range checking. Now since clojure is open source -
>> yay - I changed the aget java code to take a long and do a unckeded typecast
>> as in '(int)i' when accessing the array and made my own aget and aset
>> methods that did not typecheck (since I knew what it was called with). This
>> bought about 10% execution time.
>>
>> So what I'd suggest is to add some unckecked-aget methods that take a long
>> as index and don't typecast, for array intensive code this is a 10% speedup
>> which isn't that bad. Other then that I am still looking why clojure is
>> slower by such a magnitude.
>>
>> Also it would be great if there were a way to give functions signatures if
>> desired, as in having (aget Object) that runs (int ...) on Object and (aget
>> int/long) that does just pass the value w/o casting.
>>
>> Also the profiles show that despite my best efforts there is still a large
>> number of calls made for Number casts, I'm not sure where they are from,
>> likely from clojures core interiors.
>>
>>
>> Here are some of the results I got: http://grab.by/57x0
>>
>> and some profiling results: http://grab.by/57vO (look at the time taken
>> for intCast)
>>
>> Regards,
>> Heinz
>>
>> --
>> 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<clojure%2bunsubscr...@googlegroups.com>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>
>
> Don't have time to dive into this right now, but all I can say is now you
> are starting to have an idea what the "other side" looks like. The kind of
> hoop jumping you have to do get within 3x of Scala is absurd.
>
> This style of coding is largely unnecessary with the latest equals branch.
> However in order to be competitive you're going to have to be a bit more
> clever with your combination of deftype/record, protocols, statics:
>
> * Data locality, solved by fields with deftype/record (also allows to
> define a bunch of method/fns that have access to the field type to avoid
> cast)
> * primitive return solved by static
> * macro inlining is unnecessary with static
>

Couple other notes:

* You can use definterface to define type-hinted methods for deftype/record,
you can't do that with protocols.
* A good example of how fast protocols can be is
http://github.com/ztellman/cantor.
* Protocols and static cannot interact at the moment

-- 
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