Hi Alex, - the ^void is necessary to get the method signature right for it to compile at all - *the nil workaround "works" in that decompilation shows the method body with the addition only, no cast - thank you* - ...but makes a smaller difference to my overall execution time:-) - lesson learned (remembered): use asynchronous profiling to avoid safepoint bias - when I do that without the workaround it's clear that the addition is 50% of the observable work in that method, the Numbers.num Long.valueOf() calls the other 50% - so eliminating the cast doesn't make everything free
Thanks, Pete Windle On Monday, May 16, 2022 at 12:40:07 AM UTC+1 Alex Miller wrote: > I don't think that void type hint is going to do anything there. The > deftype impl of apply here will (has to by Java requirements) return void > here. There is a gap here I think where the return gets needlessly boxed. > You might try just putting a nil expr after the set! as a workaround. > In any case, we should definitely get a ticket filed and track this down. > > > On Sunday, May 15, 2022 at 7:11:31 AM UTC-5 pete windle wrote: > >> Hey, I'm trying to work on some performance sensitive code using Clojure >> together with the Carrotsearch HPPC library. I've come up against a weird >> behaviour of set! in conjunction with primitive maths. >> >> This example is a toy problem not a production problem, but there are >> things I might not be harder to do at work w/Clojure. >> >> I have a com.carrotsearch.hppc.LongLongHashMap and I wish to sum the >> contents of the map. They provide a com.carrotsearch.hppc.LongLongProcedure >> where an apply method is called for each k, v. >> >> Thence: >> (defprotocol ValueRetriever >> (get-value [this ^LongLongHashMap memory])) >> >> (deftype ValueAdder [^{:unsynchronized-mutable true} ^long total] >> LongLongProcedure >> (^void apply [this ^long k ^long v] >> (set! total (unchecked-add total v))) >> ValueRetriever >> (get-value [this memory] (set! total 0) (.forEach memory this) total)) >> >> To a first approximation all of the time spent summing the map is in the >> apply method as expected, however when I profile it with YourKit every >> sample taken is actually in clojure.lang.Numbers.num. Using the extremely >> handy *clj-java-decompiler *library I can try to see what's happening, >> and it looks like we're attempting to box the return value from set! >> >> public void apply(final long k, final long n) { >> Numbers.num(this.total += n); >> } >> >> >> Is there some technique I can use to stop the return value from set! >> being boxed (before the box is discarded to the void)? >> >> I do have real use cases where a rather tight aggregation loop will be >> called for many millions of values and I'd prefer not to incur this cost. >> >> Workaround is obviously to write the aggregators in Java but that's >> strongly not preferred, at the point I'm mixing modes I might as well write >> the whole core in Java. >> >> Cheers, >> >> Pete Windle >> >> -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/937375d6-1ff5-496d-8a41-8f86e7a7fb10n%40googlegroups.com.