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