Re: avoiding casts with aget & friends

2019-02-01 Thread Alexander Yakushev
The "easiest" way to obtain JIT-produced native code without having to sift 
through mountains of it is to use JMH[1] in -perfasm mode[2]. Here's an 
article on how to use JMH from Clojure[3].

However, if you start to spend so much time optimizing primitive operations 
in Clojure (and this really, really matters in your program), I'd suggest 
writing that part in Java if possible, and call from Clojure. This 
library[4] greatly improves the experience of writing Java from inside 
Clojure projects.

[1] https://openjdk.java.net/projects/code-tools/jmh/
[2] http://psy-lob-saw.blogspot.com/2015/07/jmh-perfasm.html
[3] http://clojure-goes-fast.com/blog/using-jmh-with-clojure-part1/
[4] https://github.com/ztellman/virgil

On Friday, 1 February 2019 01:10:09 UTC+2, Brian Craft wrote:

> 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  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_249: 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  6556: goto  61  
>>   58: lload_0
>> 61: pop   59: pop
>>59: invokestatic  #49
>> 62: aload_260: lload_2
>>   62: goto  69
>> 63: aconst_null   61: lstore4
>>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 

Re: Text replacement capability in clojure macros (just like C #define)

2019-02-01 Thread Ben Sima
f...@helpshift.com writes:

> I want to write a macro
>
> (defmacro params [] 'a 'b 'c)
>
> that will be used in places like this
>
>  ;; without macro
>   (fnc a b c)
>
>   ;; with macro
>   (fnc pararms) => (fnc a b c)

If you have a list of params, you can apply a function to it like so:

(apply fnc params)

e.g.

(apply + [1 2 3]) ;=> 6

No macro needed. 'apply' is just another function.

Does that help?

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


Text replacement capability in clojure macros (just like C #define)

2019-02-01 Thread faiz
I want to write a macro

(defmacro params [] 'a 'b 'c)

that will be used in places like this

 ;; without macro
  (fnc a b c)

  ;; with macro
  (fnc pararms) => (fnc a b c)

If you see this could be easily done by C's #define which was just a text 
replacement

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