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

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