Is there any way to inspect what the jit does to it? On Wednesday, January 30, 2019 at 10:07:38 PM UTC-8, Alex Miller wrote: > > > > On Wed, Jan 30, 2019 at 11:07 PM Brian Craft <craft...@gmail.com > <javascript:>> wrote: > >> With much experimentation, I ended up with this: >> >> (let [a 1 >> b (.longValue ^Long (:foo {:foo 3})) >> c (if (< a b) a b)]) >> >> which seems to avoid the longCast call: >> >> Object o; >> if (_thunk__0__ == (o = _thunk__0__.get(const__3))) { >> o = (__thunk__0__ = >> __site__0__.fault(const__3)).get(const__3); >> } >> final long b = (long)o; >> final long c = (a < b) ? a : b; >> >> I don't know if this is advisable. Does anyone do this? >> > > No, I wouldn't do this. `long` can inline so it's going to be better (it's > also more likely to jit well as it's used other places and is likely hotter > in the jit). > > Going back to the original... > > (let [a 1 > b (:foo {:foo 3}) > c (if (< a b) a b)]) > > let will track primitives if possible. > - a is going to be a primitive long. > - (:foo {:foo 3}) is going to (always) return an Object and it's best to > recognize that and make an explicit cast to a primitive long. > - if a and b are both primitives, then < is able to inline a > long-primitive comparison (via Numbers.lt()) > - the if is going to return an Object though, so again you'll probably > want to type hint or cast c, but it's hard to know for sure without seeing > more code > > Without other info, I would probably start with > > (let [a 1 > b (long (:foo {:foo 3})) > c (if (< a b) a b)]) > > Or alternately, it might be better to just type hint b in the comparison > to avoid reboxing b, but hard to know without more context: > > (let [a 1 > b (:foo {:foo 3}) > c (if (< a ^long b) a b)]) > > Comparing the bytecode for these (skipping everything up through the > keyword lookup, which is same for all): > > Original: Option 1: > Option 2: > 45: astore_2 45: invokestatic #41 45: > astore_2 > 46: lload_0 48: lstore_2 > 46: lload_0 > 47: aload_2 49: lload_0 > 47: aload_2 > 48: invokestatic #41 50: lload_2 > 48: checkcast #37 > 51: ifeq 62 51: lcmp > 51: invokestatic #43 > 54: lload_0 52: ifge 60 > 54: lcmp > 55: invokestatic #45 55: lload_0 > 55: ifge 66 > 58: goto 65 56: goto 61 > 58: lload_0 > 61: pop 59: pop > 59: invokestatic #49 > 62: aload_2 60: lload_2 > 62: goto 69 > 63: aconst_null 61: lstore 4 > 65: pop > 64: astore_2 63: lload 4 > 66: aload_2 > 65: astore_3 65: invokestatic #47 67: > aconst_null > 66: aload_3 > 68: astore_2 > 67: aconst_null > 69: astore_3 > 68: astore_3 > 70: aload_3 > > 71: aconst_null > > 72: astore_3 > > Option 1 does an lstore/lload (long) instead of an astore/lstore (object). > Both options use lcmp which is likely the fastest path to compare longs. > I've omitted some info here to make these fit, but Original line 48 will > invoke Numbers.lt:(JLjava/lang/Object;)Z which is the Numbers.lt(long, > Object) - lcmp is definitely going to be preferable to this. Also of > importance is that in Option 1, both a and b are stored as longs and loaded > as longs so if there is subsequent stuff to do on them, they can avoid > boxing (this is also betrayed by the shorter length from fewer casts). > > Your longValue one is like Option 1, but starts: > > 45: checkcast #37 // class java/lang/Long > 48: invokevirtual #41 // Method > java/lang/Long.longValue:()J > > I guess I don't know whether that's faster than an invokestatic call to > clojure/lang/RT.longCast:(Ljava/lang/Object;)J, hard to tell without > testing in a real context. I'd certainly use the (long ...) one though > unless I proved it mattered. > >
-- 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/d/optout.