I've noticed a related performance bottleneck when working with
clojure on dalvik.  Without type hints methods get looked up using
reflection every time using clojure.lang.Reflector.getMethods. A lot
if time is spend in this method while the results can easily be
cached.  This is probably only related to code calling Java (or other
non-clojure) methods.

For my work on dalvik, I patched getMethods:

  
http://github.com/remvee/clojure/commit/90d31c63b1b2a1fe5ee0ba9ab30915ed039d0fe5

Question to the core contributors: should I open an issue with a patch
for this?  Or are there better ways to solve this?


On Sun, Mar 15, 2009 at 3:03 AM, Scott Fraser <scott.e.fra...@gmail.com> wrote:
>
> Hi Larry
>
> I have a performance tweak, that gives about an order of magnitude
> speedup to paint-cells when running this with a large grid and no or
> little (Thread/sleep life-delay) in toggle-thread. That is how I am
> running it now - 128 x 192 cells with no delay! It is also noticeably
> faster on the more typical size grid.
>
> Type hint is on the graphics param:
>
> (defn paint-cells [#^java.awt.Graphics graphics]
>    (time (doseq [[[x,y] state] @cells]
>         (doto graphics
>            (. setColor (if state Color/RED Color/WHITE))
>            (. fillRect (* cell-size x) (* cell-size y) cell-size cell-
> size)))))
>
> Example, with type hint:
>
> "Elapsed time: 45.871193 msecs"
> "Elapsed time: 39.209662 msecs"
> "Elapsed time: 43.899504 msecs"
>
> Without:
>
> "Elapsed time: 529.635331 msecs"
> "Elapsed time: 438.145769 msecs"
> "Elapsed time: 442.839872 msecs"
>
> I would imagine there may be some other way to get clojure to cache
> the reflected handle to Graphics, but I am still a little new to this
> so don't have any other ideas on how to eliminate the high amount of
> reflection without a type hint.
>
> -Scott
> http://fraser.blogs.com/
>
> On Mar 4, 4:17 pm, Larry Sherrill <lps...@gmail.com> wrote:
>> I've incorporated everyone's suggestions and thought I would post the
>> resulting smaller code. I refactored init-cells away and just pass in
>> an init or new function to calc-state to reuse the for loop. I made
>> determine-next-state a little more verbose than technically necessary
>> to makeconway'srules more obvious to me. The refs "cells" and
>> "running" don't feel very functional but I don't know how to get rid
>> of them.
>>
>> (import '(javax.swing JFrame JPanel JButton)
>>         '(java.awt BorderLayout Dimension Color)
>>         '(java.awt.event ActionListener))
>>
>> (def cells (ref {}))
>>
>> (def running (ref false))
>>
>> (defn determine-initial-state [x y]
>>   (= 0 (rand-int 5)))
>>
>> (defn determine-new-state [x y]
>>   (let [neighbor-count
>>          (count (for [dx [-1 0 1] dy [-1 0 1]
>>                   :when (and (not (= 0 dx dy))
>>                              (cells [(+ x dx) (+ y dy)]))]
>>                   :alive))]
>>     (if (cells [x y])
>>         (< 1 neighbor-count 4)
>>         (= neighbor-count 3))))
>>
>> (defn calc-state [cell-state]
>>   (dosync
>>     (ref-set cells
>>       (reduce conj {}
>>         (for [x (range 32) y (range 48)]
>>           [[x y] (cell-state x y)])))))
>>
>> (defn paint-cells [graphics]
>>      (doseq [[[x, y] state] @cells]
>>        (doto graphics
>>          (. setColor (if state Color/RED Color/WHITE))
>>          (. fillRect (* 10 x) (* 10 y) 10 10))))
>>
>> (defn toggle-thread [panel button]
>>     (if @running
>>
>>       (do (dosync (ref-set running false))
>>           (. button (setText "Start")))
>>
>>       (do (dosync (ref-set running true))
>>           (. button (setText "Stop"))
>>           (. (Thread.
>>                  #(loop []
>>                     (calc-state determine-new-state)
>>                     (. panel repaint)
>>                     (Thread/sleep 100)
>>                     (if @running (recur))))
>>                  start))))
>>
>> (defn main[]
>>
>>     (calc-state determine-initial-state)
>>
>>     (let [f (JFrame.)
>>           b (JButton. "Start")
>>           panel (proxy [JPanel] [] (paint [graphics] (paint-cells
>> graphics)))]
>>
>>         (doto f
>>             (. setLayout (BorderLayout.))
>>             (. setLocation 100 100)
>>             (. setPreferredSize (Dimension. 320 540))
>>             (. add b BorderLayout/SOUTH)
>>             (. add panel BorderLayout/CENTER)
>>             (. setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
>>             (. pack)
>>             (. setVisible true))
>>
>>         (. b addActionListener
>>            (proxy [ActionListener] []
>>                 (actionPerformed [evt] (toggle-thread panel b))))))
>>
>> (main)
>>
>> Thanks for everyone. Very good learning experience.
>> Larryhttp://lpsherrill.blogspot.com
>
> >
>

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

Reply via email to