On Wed, Dec 22, 2010 at 12:52 PM, Rayne <disciplera...@gmail.com> wrote: > I have a piece of code, and I'd like to see how fast it can be. > > (defn count-num-chars [^String s] > (loop [s s acc 0] > (if (seq s) > (recur (rest s) (if (= (first s) \space) acc (inc acc))) > acc))) > > This is the fastest I've been able to get it. The function is very > simple. It takes a string and counts the number of non-space > characters inside of that string. > > I've been testing this code against a 460 non-space character string. > Here is the entire source, benchmarking and all: > > (def s (apply str (repeat 20 "This is a really long string"))) > > (defn count-num-chars [^String s] > (loop [s s acc 0] > (if (seq s) > (recur (rest s) (if (= (first s) \space) acc (inc acc))) > acc))) > > (println "Chars outputted:" (count-num-chars s)) > > (let [before (System/nanoTime)] > (dotimes [_ 1000] > (count-num-chars s)) > (let [after (System/nanoTime)] > (println "Time (in nanoseconds):" (/ (- after before) 1000.0)))) > > Running it gives me around 137343.295 nanoseconds.
I get around half that. Yours calls seq every loop. Writing (defn count-num-chars [^String s] (loop [s (seq s) acc 0] (if s (recur (next s) (if (= (first s) \space) acc (inc acc))) acc))) results in about 10% savings. Using primitive math: (defn count-num-chars [^String s] (loop [s (seq s) acc (int 0)] (if s (recur (next s) (if (= (first s) \space) acc (unchecked-inc acc))) acc))) yields up another 10% or so. That's maybe 40,000ns, still over 10x slower than the Java implementations you mentioned, but it's about the limits of the savings we'll get while still using the seq abstraction, I suspect. To get closer to Java performance means getting closer to Java means of doing it: (defn count-num-chars [^String s] (let [l (int (.length s))] (loop [i (int 0) acc (int 0)] (if (< i l) (recur (unchecked-inc i) (if (= (.charAt s i) \space) acc (unchecked-inc acc))) acc)))) 15k nsec -- twice as fast as before. Still 5x slower than Java; I'm not sure why. This is now directly equivalent to the obvious Java implementation, int l = s.length(); int acc = 0; for (i = 0; i < l; ++i) if (s.charAt(i) == ' ') ++acc; and since the string is type-hinted it shouldn't be using reflection for the length or charAt calls. -- 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