JIT will probably remove unnecessary checkcast instructions. What looks
suspicious to me is that i and asize are converted to longs (notice i2l
opcodes). I noticed earlier that loops with long counters are measurably
slower for the same number of iterations (probably, HotSpot does not
apply some optimizations in this case).

Leon Barrett <lbarr...@climate.com> writes:

> Hi. I've been working with people at Prismatic to optimize some simple math 
> code in Clojure. However, it seems that Clojure generates an unnecessary 
> type check that slows our (otherwise-optimized) code by 50%. Is there a 
> good way to avoid this, is it a bug in Clojure 1.5.1, or something else? 
> What should I do to work around this?
>
> Here's my example. The aget seems to generate an unnecessary 
> checkcastbytecode. I used Jasper and Jasmin to decompile and recompile 
> Bar.class 
> into Bar_EDITED.class, without that bytecode. The edited version takes 
> about 2/3 the time.
>
> (ns demo
>   (:import demo.Bar_EDITED))
>
> (definterface Foo
>   (arraysum ^double [^doubles a ^int i ^int asize ^double sum]))
>
> (deftype Bar []
>   Foo
>   (arraysum ^double [this ^doubles a ^int i ^int asize ^double sum]
>     (if (< i asize)
>       (recur a (unchecked-inc-int i) asize (+ sum (aget a i)))
>       sum)))
>
> (defn -main [& args]
>   (let [bar (Bar.)
>         bar-edited (Bar_EDITED.)
>         asize 10000
>         a (double-array asize)
>         i 0
>         ntimes 10000]
>     (time
>
>       (dotimes [iter ntimes]
>         (.arraysum bar a i asize 0)))
>     (time
>       (dotimes [iter ntimes]
>         (.arraysum bar-edited a i asize 0)))))
>
>
> ;; $ lein2 run -m demo
> ;; Compiling demo
> ;; "Elapsed time: 191.015885 msecs"
> ;; "Elapsed time: 129.332 msecs"
>
>
> Here's the bytecode for Bar.arraysum:
>
>   public java.lang.Object arraysum(double[], int, int, double);
>     Code:
>        0: iload_2       
>        1: i2l           
>        2: iload_3       
>        3: i2l           
>        4: lcmp          
>        5: ifge          39
>        8: aload_1       
>        9: iload_2       
>       10: iconst_1      
>       11: iadd          
>       12: iload_3       
>       13: dload         4
>       15: aload_1       
>       16: aconst_null   
>       17: astore_1      
>       18: checkcast     #60                 // class "[D"
>       21: iload_2       
>       22: invokestatic  #64                 // Method 
> clojure/lang/RT.intCast:(I)I
>       25: daload        
>       26: dadd          
>       27: dstore        4
>       29: istore_3      
>       30: istore_2      
>       31: astore_1      
>       32: goto          0
>       35: goto          44
>       38: pop           
>       39: dload         4
>       41: invokestatic  #70                 // Method 
> java/lang/Double.valueOf:(D)Ljava/lang/Double;
>       44: areturn       
>
>
> As far as I can tell, Clojure generated a checkcast opcode that tests on 
> every loop to make sure the double array is really a double array. When I 
> remove that checkcast, I get a 1/3 speedup (meaning it's a 50% overhead).
>
> Can someone help me figure out how to avoid this overhead?
>
> Thanks.
>
> - Leon Barrett
>
> -- 
> -- 
> 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/groups/opt_out.
>
>

-- 
Mikhail

Attachment: pgpHYSTT9m844.pgp
Description: PGP signature

Reply via email to