On Jun 14, 7:00 pm, tmountain <tinymount...@gmail.com> wrote:
> I've been playing around with rewriting some Java code in Clojure and
> did some simple benchmarking in the process. In this case, there's a
> huge disparity in the performance numbers between the two languages,
> and I'm wondering what the cause may be. The program rotates a string
> from "aaaa", "aaab", ..., "zzzz". The Java version takes 0.77 seconds
> to complete while the Clojure version takes 22 seconds. I've tried to
> make the scripts relatively isomorphic and have verified that they
> produce the same results. I'm pasting the source below.
>

Here is a clojure version that runs significantly faster
on my system. The main optimizations I have done are
coercion to primitives and using unchecked ops.
As I understand it, the original clojure version is slow
because its safer (checks for overflows etc.).

(defn xbase26 [n]
  (let [seed-string "aaaa"
        s (new StringBuilder seed-string)
        a_val (int \a)]
    (loop [pos 3 x (int n)]
      (when (pos? x)
        (let [digit (char (+ a_val (unchecked-remainder x 26)))]
          (.setCharAt s pos digit)
          (when (pos? pos)
            (recur (int (dec pos)) (unchecked-divide x 26))))))
    (.toString s)))

These are the numbers I see:

;; java
[clojure]% time java -cp .
Base26
java -cp . Base26  0.40s user 0.02s system 88% cpu 0.476 total

;; original
[clojure]% time java -cp .:classes:/home/parthm/src/clojure/
clojure.jar base26
java -cp .:classes:/home/parthm/src/clojure/clojure.jar base26  33.08s
user 1.18s system 99% cpu 34.456 total
[clojure]%

;; optimized
[clojure]% time java -cp .:classes:/home/parthm/src/clojure/
clojure.jar base26
java -cp .:classes:/home/parthm/src/clojure/clojure.jar base26  1.75s
user 0.11s system 104% cpu 1.784 total


While this works well, I more optimization may
be possible by choosing an algorithm thats more suited
and ideomatic for clojure. I suppose that intent here
is to do a micro-benchmark.

Regards,
Parth


> tra...@travis-ubuntu:/tmp% time clj base26.clj
> clj base26.clj  21.99s user 1.23s system 85% cpu 27.318 total
>
> tra...@travis-ubuntu:/tmp% time java Base26
> java Base26  0.77s user 0.04s system 78% cpu 1.029 total
>
> clojure version:
>
> (defn base26 [n]
>   (let [seed-string "aaaa"
>         s (new StringBuilder seed-string)]
>     (loop [pos (- (count seed-string) 1)
>            x n]
>       (if (> x 0)
>         (let [digit (+ (int \a) (mod x 26))]
>           (. s setCharAt pos (char digit))
>           (if (and (> pos 0) (> x 0))
>             (recur (- pos 1) (/ x 26))))))
>     (. s toString)))
>
> (doseq [i (range (Math/pow 26 4))]
>     (base26 i))
>
> java version:
>
> import java.lang.StringBuilder;
>
> public class Base26 {
>     public static void main(String[] args) {
>         for (int i = 0; i < Math.pow(26, 4); i++) {
>             Base26.base26(i);
>         }
>     }
>
>     public static String base26(int num) {
>         if (num < 0) {
>             throw new IllegalArgumentException("Only positive numbers
> are supported");
>         }
>         StringBuilder s = new StringBuilder("aaaa");
>         for (int pos = 3; pos >= 0 && num > 0 ; pos--) {
>             char digit = (char) ('a' + num % 26);
>             s.setCharAt(pos, digit);
>             num = num / 26;
>         }
>         return s.toString();
>     }
>
> }
>
> I've tried warn-on-reflection, and it didn't report anything.
>
> Thanks,
> Travis
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to