I got it down to about 3 seconds. I did what William said, but the biggest improvement was from changing the way *width*, *height*, and *max-steps* were defined. I noticed that in the Java version they are constants, but in the Clojure version they are Vars which means that inside your tight inner loops you are dereferencing the vars multiple times. Vars are for thread local values, but these values are not expected to change. I'm not sure the best way to make these vars into constants, but I changed them into macros:
(defmacro *width* [] (float 640)) Then replaced instances of *width* with (*width*). The macros will get compiled down to floats instead of resulting in multiple Var.deref calls (and probably Number.floatValue calls) per loop iteration. Here is the code: (ns main (:import (java.awt Color Container Graphics Canvas Dimension) (javax.swing JPanel JFrame) (java.awt.image BufferedImage BufferStrategy))) (set! *warn-on-reflection* true) (defmacro *width* [] (float 640)) (defmacro *height* [] (float 640)) (defmacro *max-steps* [] (float 32)) (defn on-thread [#^Runnable f] (doto (new Thread f) (.start))) (defn check-bounds [x y] (loop [px (float x) py (float y) zx (float 0.0) zy (float 0.0) zx2 (float 0.0) zy2 (float 0.0) value (float 0)] (if (and (< value (*max-steps*)) (< (+ zx2 zy2) (float 4.0))) (let [new-zy (float (+ (* (float 2.0) zx zy) py)) new-zx (float (+ (- zx2 zy2) px)) new-zx2 (float (* new-zx new-zx)) new-zy2 (float (* new-zy new-zy))] (recur px py new-zx new-zy new-zx2 new-zy2 (inc value))) (if (== value (*max-steps*)) 0 value)))) (defn draw-line [#^Graphics g y] (let [dy (- 1.25 (* 2.5 (/ y (*height*))))] (doseq [x (range 0 (*width*))] (let [dx (- (* 2.5 (/ x (*width*))) 2.0)] (let [value (check-bounds dx dy)] (if (> value 0) (doto g (. setColor (Color. (* value (/ 255 (*max-steps*))))) (. drawRect x y 0 0)))))))) (defn draw-lines ([buffer g] (draw-lines buffer g (*height*))) ([#^BufferStrategy buffer g y] (doseq [y (range 0 y)] (draw-line g y) ;(on-thread (draw-line g y)) (. buffer show)))) (defn draw [#^Canvas canvas] (let [buffer (. canvas getBufferStrategy) g (. buffer getDrawGraphics)] (draw-lines buffer g))) (defn main [] (let [panel (JPanel.) canvas (Canvas.) frame (JFrame. "Mandelbrot")] (doto panel (.setPreferredSize (Dimension. (*width*) (*height*))) (.setLayout nil) (.add canvas)) (doto frame (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.setBounds 0,0,(*width*) (*height*)) (.setResizable false) (.add panel) (.setVisible true)) (doto canvas (.setBounds 0,0,(*width*) (*height*)) (.setBackground (Color/BLACK)) (.createBufferStrategy 2) (.requestFocus)) (draw canvas))) (time (main)) ~$ clojure /tmp/mandelbrot.clj "Elapsed time: 3577.128587 msecs" Paul --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---