I know the full answer is "run performance tests and see", and/or "read the byte code produced by the Clojure compiler and think hard", but was looking for maybe quicker advice here. If there is some Clojure/Java code that frequently pulls 32-bit int's out of arrays, puts them into let-bound symbols, does a little bit of arithmetic and/or comparisons on them, and sometimes stores them back into int arrays, it is going to be perfectly normal to get boxed math warnings when one compiles the code using (set! *unchecked-math* :warn-on-boxed)
.
I believe that fn parameters can be type-hinted to be long or double primitive types, and the Clojure compiler can support passing those unboxed.
Can it support let-bound symbols as 32-bit int, unboxed? Or is that also restricted to long and double?
If not, then I am guessing perhaps the most efficient code can be produced in this scenario by converting to primitive long when pulling ints out of the arrays, manipulating them as long, then converting them back to int just before storing them back into int array.
let bound symbols can be int prims I think
ok, good for me to do some focused experiments around that to verify it.
the first 2 bullets there being the important ones
Resisting the urge to see when those docs were last updated -- They are definitely getting more impressive over time. Thanks!
that's been there since 1.3 I think
FYI John Rose the JVM architect just filed an issue where hotspot doesn't apply loop optimizations when the trip counter is a long, only when it's an int
Yes, this is related to such loops being considered "uncounted" . Some more surprising examples here: http://psy-lob-saw.blogspot.com/2016/02/wait-for-it-counteduncounted-loops.html ("Counted Loops?" section) Also here some notes about uncounted loops and their negative impact on optimizations: http://psy-lob-saw.blogspot.com/2015/12/safepoints.html (search for "negated")
That comment of mine was intended to express: "Wow, that is more than I remember reading there before, which may have been a long time ago", not "that looks old/out of date"
https://web.archive.org/web/20080710050619/http://clojure.org/java_interop - the oldest version on wayback machine from 2008 has it :)
I believe it is still accurate
but I would check the generated bytecode to be sure
I believe the intention is that you should be able to write hot loops on primitives though if you are sufficiently careful to avoid boxed calls
Excellent. Hopefully I can make this thing sing.
Vector API in Clojure! 🙂 https://gist.github.com/schmee/d1a705acc49a2f5f08e34fcddfe736e7
@ghadi ^
0x000000011f8aced3: vmovdqu ymm0,YMMWORD PTR [r12+r10*8+0x10]
0x000000011f8aceda: vmovdqu ymm1,YMMWORD PTR [r12+r8*8+0x10]
0x000000011f8acee1: vpaddd ymm0,ymm1,ymm0
0x000000011f8acee5: vmovdqu YMMWORD PTR [rax+0x10],ymm0
that’s what I like to see! :godmode:
nice
so it does inline across Fn's
that will be huge for Tensorflow-like libs on the JVM
Java’s gettin’ fast
and so is Clojure it seems 😄
There is some odd edge cases on comment+reader-macro
(clojure.tools.reader/read-string {:read-cond :allow} "[#_#?(:foo [])]")
that's pretty weird
no wait
I think it makes sense
me too
there's no :clojure
expansion
so it's equivalent to [#_]
#?(:foo [])
yields nothing read
not nil, but literally nothing
reading [#_#?(:foo 42) 43 44]
might make the behavior clear
you could throw a :default
branch in there to actually read as nil
(read-string {:read-cond :allow} "[#_#?(:foo [] :default nil)]")