The reason foo2 is faster is that foo1 is passing a primitive long value to cb, which caused boxing. Without that, the performance seems to be exactly the same, which it should be!
On Apr 25, 6:50 pm, Alice <dofflt...@gmail.com> wrote: > Wow! That's awesome. It's even faster! Thanks. > > (defn foo1 [^long l cb] (cb l)) > (defn foo2 [^long l cb] (invoke-primitive O [L] cb l)) > > (time > (dotimes [n 1000000] > (foo1 n (fn [l] nil)))) > > (time > (dotimes [n 1000000] > (foo2 n (fn [^long l] nil)))) > > "Elapsed time: 7.622627 msecs" > "Elapsed time: 5.341534 msecs" > > On Apr 25, 4:17 pm, Gunnar Völkel <gunnar.voel...@googlemail.com> > wrote: > > > > > > > > > Some time ago I dug into primitive type hints and how the Clojure compiler > > uses them. > > When the compiler finds primitive type hints on a function, say (defn f > > [^long n] ...), the generated class for that function implements a > > primitive interface, IFn$LO in this case, > > and generates appropriate code in the interface's only method Object > > invokePrim(long arg0). > > > For a defn which is used as symbol in code the compiler detects the > > primitive interface and generates code using invokePrim if the infered type > > of the parameters matches. > > Long story short, currently the compiler is not able to use primitive > > invocation for higher order functions automatically because it would need > > to generate code that checks at runtime. > > > You can fix this with Java interop. I implemented an `invoke-primitive` > > macro over here:https://gist.github.com/guv/5458038 > > It could be used like follows: > > (defn calc [^long n] ...) > > (defn dosomething [f, ^long n] > > (invoke-primitive O [L] f n)) > > > The macro expands to (.invokePrim ^IFn$LO f n) using several checks at > > compile time. > > > Am Mittwoch, 24. April 2013 19:15:49 UTC+2 schrieb Alice: > > > > So, is there a way to type hint on cb that it has a function accepting > > > a long argument? > > > > On Apr 25, 12:55 am, Stuart Sierra <the.stuart.sie...@gmail.com> > > > wrote: > > > > I'm taking a guess here: The compiler doesn't know the type signature of > > > > `cb` when compiling `foo`, so it's going to use the IFn.invoke(Object) > > > > signature. Clojure's type inference is only local, and it won't assume > > > that > > > > a primitive-type signature is available for an arbitrary function. > > > > > So there's probably some extra typecasting going on when `fn` is > > > > type-hinted to a primitive. > > > > > In general, type-hinting to primitive types doesn't do you any good in > > > the > > > > presence of higher-order functions like `map`. > > > > > -S > > > > > On Wednesday, April 24, 2013 11:35:11 AM UTC-4, Alice wrote: > > > > > > (defn foo [^long l cb] (cb l)) > > > > > > (time > > > > > (dotimes [n 1000000] > > > > > (foo n (fn [l] nil)))) > > > > > > (time > > > > > (dotimes [n 1000000] > > > > > (foo n (fn [^long l] nil)))) > > > > > > "Elapsed time: 7.861 msecs" > > > > > "Elapsed time: 11.770973 msecs" > > > > > > Why is the latter slower? -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.