clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
2019-08-06T11:20:20.189200Z

I spent I-don’t-know-how-many days digging around the core.rrb-vector code at one job that used it. CRRBV-8 and 9 and 10 were fun to debug. (We changed the approach to better use of built in data structures in the end)

2019-08-06T15:59:25.189400Z

I hear you. There is definitely enough code there that it takes some orientation before you have much hope of fixing it.

2019-08-06T17:40:18.192900Z

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

2019-08-06T17:40:42.193400Z

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.

2019-08-06T17:41:05.194Z

Can it support let-bound symbols as 32-bit int, unboxed? Or is that also restricted to long and double?

2019-08-06T17:44:32.195300Z

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.

alexmiller 2019-08-06T18:03:16.195600Z

let bound symbols can be int prims I think

2019-08-06T18:04:37.196100Z

ok, good for me to do some focused experiments around that to verify it.

alexmiller 2019-08-06T18:10:30.196300Z

https://clojure.org/reference/java_interop#primitives

alexmiller 2019-08-06T18:10:57.196600Z

the first 2 bullets there being the important ones

2019-08-06T18:13:07.198Z

Resisting the urge to see when those docs were last updated -- They are definitely getting more impressive over time. Thanks!

alexmiller 2019-08-06T18:13:55.199400Z

that's been there since 1.3 I think

ghadi 2019-08-06T18:14:03.199900Z

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

jumar 2019-08-07T07:22:25.235Z

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

2019-08-06T18:14:23.200500Z

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"

alexmiller 2019-08-06T18:19:09.200900Z

https://web.archive.org/web/20080710050619/http://clojure.org/java_interop - the oldest version on wayback machine from 2008 has it :)

alexmiller 2019-08-06T18:19:54.201200Z

I believe it is still accurate

alexmiller 2019-08-06T18:20:27.201500Z

but I would check the generated bytecode to be sure

alexmiller 2019-08-06T18:21:06.202300Z

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

2019-08-06T18:37:10.202600Z

Excellent. Hopefully I can make this thing sing.

schmee 2019-08-06T18:53:46.202900Z

Vector API in Clojure! 🙂 https://gist.github.com/schmee/d1a705acc49a2f5f08e34fcddfe736e7

schmee 2019-08-06T18:54:04.203200Z

@ghadi ^

schmee 2019-08-06T18:54:18.203400Z

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

schmee 2019-08-06T18:54:26.203700Z

that’s what I like to see! :godmode:

ghadi 2019-08-06T18:54:33.203900Z

nice

ghadi 2019-08-06T18:54:48.204300Z

so it does inline across Fn's

ghadi 2019-08-06T18:55:10.204600Z

that will be huge for Tensorflow-like libs on the JVM

schmee 2019-08-06T18:59:28.204900Z

Java’s gettin’ fast

schmee 2019-08-06T18:59:37.205200Z

and so is Clojure it seems 😄

2019-08-06T19:06:20.205300Z

Yep! Good effort in taking it on

souenzzo 2019-08-06T21:16:44.206200Z

There is some odd edge cases on comment+reader-macro (clojure.tools.reader/read-string {:read-cond :allow} "[#_#?(:foo [])]")

2019-08-06T21:17:48.206400Z

that's pretty weird

2019-08-06T21:38:09.207100Z

no wait

2019-08-06T21:38:15.207400Z

I think it makes sense

alexmiller 2019-08-06T21:38:18.207600Z

me too

2019-08-06T21:38:29.208100Z

there's no :clojure expansion

2019-08-06T21:38:33.208500Z

so it's equivalent to [#_]

1👍
alexmiller 2019-08-06T21:38:34.208600Z

#?(:foo []) yields nothing read

alexmiller 2019-08-06T21:39:15.208900Z

not nil, but literally nothing

2019-08-06T21:40:43.209400Z

reading [#_#?(:foo 42) 43 44] might make the behavior clear

alexmiller 2019-08-06T21:41:34.209800Z

you could throw a :default branch in there to actually read as nil

alexmiller 2019-08-06T21:41:37.210Z

(read-string {:read-cond :allow} "[#_#?(:foo [] :default nil)]")