> My question is how to find performance bottlenecks in Clojure
> applications.
> Second question is about my code. Where are the problem?
> May be this is
> 1. Incorrect execution time measuring procedure
> 2. Bad algorithm
> 3. Slow input/output (read from System.in stream/ printing to
> System.out) in Clojure
>
One rule of thumb when performance tuning clojure code is to (set!
*warn-on-reflection* true) at the top of your code.
In your case, there is one reflection warning in your loop that I bet
will get a large part of your performance back.
Also, your recursive call is in tail-position, so you can use recur
which is basically compiled down to a goto rather than a function
call. This will save stack and probably run faster.
How does the following work for you?
(defn getNextInt [#^Scanner scanner term f x]
(if (not= x nil)
(apply f [x]))
(let [val (. scanner nextInt)]
(if (not= val term)
(recur scanner term f val))))
Try with this, which is closer to the java version:
; in a file scan/core.clj
(ns scan.core
(:import java.util.Scanner)
(:gen-class))
(defn -main []
(let [sc (Scanner. System/in)]
(loop [num (int (.nextInt sc))]
(when-not (= 42 num)
(println num)
(recur (.nextInt sc))))))
2011/4/19 Michael Golovanov <mike.go...@gmail.com>:
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
(apply f [x]) can be replaced by (f x)
(not= x nil) can be (almost) replaced by x if you know x cannot be the
value 'false' (sufficient in your case)
(. scanner nextInt) is a somewhat deprecated form. Write it (.nextInt scanner)
(fn [x] (println x)) is just println => you can pass println function "as is"
Try hard avoiding direct recursive function calls like (def f [...]
... (f ...))) => this fills the stack, and the JVM has a stack limited
in size.
Prefer the use of recur (when possible ! => it is in your case)
Side note.
If you were not in a case where you're seeking for the max perf., you
would probably address the problem differently : decompose the problem
in multisteps.
For example, here, you could have a function whose purpose is to
create a sequence of vals from the input:
(defn incoming-ints [in]
(let [sc (java.util.Scanner. in)]
(repeatedly #(.nextInt sc))))
Then you would walk over this sequence while its value is different from 42 :
(doseq [i (incoming-ints System/in) :while (not= i 42)]
(println i))
HTH,
--
Laurent
2011/4/19 Michael Golovanov <mike.go...@gmail.com>:
There is additional initialization time when you start up a JVM running Clojure, even if it is just a "Hello, world" Clojure program with negligible compile time.
If you are curious to see some run times for Hello, world in Java and Clojure for several different JVMs on the same hardware, but different OSs, I've published some measurements here:
Click on the "table of hello world results" link.
The earlier links are for slight modifications of many Clojure programs submitted to the Computer Language Benchmarks Game web page, comparing their run time with Clojure 1.2 and Clojure 1.3alpha6.
Andy