On Sun, Feb 13, 2011 at 5:50 PM, Jarl Haggerty <jarlhagge...@gmail.com> wrote: > For a while I've been working on a 2D physics engine written in > Clojure. I just recently got to the point where I can run a > simulation(a box falling onto the ground) and it is painfully slow. > I'm shooting for 60 fps but I can barely get 10 when the box is > falling and when it lands on the ground and the collision response > kicks in I get about 5. > > The project has reached a size where I thought it would be silly to > ask for specific ways to speed up but I thought I could at least ask a > general question. > > I have heard that Clojure is not suited for programs that need to run > in real time, is that true?
No. But you need to optimize carefully to make the inner loop fast. 1. Give some thought to the algorithm. Are you recalculating something you could reuse? Are you calculating something you never use? 3D games get a big speed boost from ignoring or reducing the precision of calculations for things that take place out of sight or far from any player's vantage point. There may be similar speedups possible in your physics engine. For example, objects in static equilibrium can be flagged "ignore" until something touches them. 2. Do not use global vars in your inner loop. Copy them to a local first: (def my-constant 42) ... (let [my-constant my-constant] (loop [...] ...)) Clojure's Var objects involve Java ThreadLocals. ThreadLocals are slow. 3. That applies to functions too, including clojure.core functions. But see below. 4. Unless you're using 1.3 or later, put the innermost loop in a single function and try to avoid calling sub-functions, except for operators like + that can get inlined. 5. Working inside a single function lets you use unboxed primitive arithmetic: (let [t (int 3) u (int some-variable)] ...) and likewise with loop. 6. Binary +, *, -. and / are particularly fast on primitives; unchecked-add etc. are even faster but wrap around on overflow. 7. The recurs in a loop with primitives need to have corresponding primitive types where the loop variables are primitive. If you get errors about recur args needing to be primitive, your math is still getting boxed somewhere. 8. If there are any Java method calls in your inner loop, type hint the heck out of the references to the objects you call them on to avoid reflection, which is uberslow. Use (set! *warn-on-reflection* true) to locate places where reflection is still being used. 9. Sometimes the fastest algorithm is a dirty one. If need be, use arrays. They're mutable, can hold primitives, but sure as hell aren't thread safe. Don't let arrays escape the thread that uses them, or preferably even your inner-loop function. If an array holds the result and the array isn't huge copy it into a vector with (into [] the-array) and return the vector, after exiting the loop. Otherwise call seq on it and return that, though that's a bit less thread-safe: if two of the elements are realized and a third gets twiddled, the third element of the seq will come out the altered value instead of the one that was in the array when the seq was constructed. 10. Watch for reflection warnings when using arrays. Don't bother with aset-int and friends either. 11. If you really must you can always drop down to Java for the bits that need to be fastest. But this is rarely if ever actually necessary. Post specific bits that are giving you trouble (recalcitrant reflection warnings, etc.) here if you continue to have trouble. -- 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