On Jun 14, 7:00 pm, tmountain <[email protected]> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---