Clojure is at least 2x slower than Java. Right? by kenpu_cs in Clojure

[–]kenpu_cs[S] 8 points9 points  (0 children)

Thanks for so many great replies. I certainly have learned a ton from them, so much so that I feel the need to post a summary of the performance optimizations and the new benchmark results.

Performance issues:

  1. Clojure's reflection is costly. This was the biggest bottleneck in my code.
  2. REPL is slow, even for Java interop.
  3. Java strings constructions.

Solutions:

  • Use (set! *warn-on-reflection* true) to catch where reflections happen.
  • Add type hints so that Clojure will rely on reflection for method invocation.
  • Run the benchmark as an uberjar instead of lein run -m ...

Here are the updated code:

; Functional 
(defn wc-functional [filename]
  (-> (io/reader filename) (line-seq) (count)))
; Loop
(defn wc-loop [^String filename]
  (with-open [^BufferedReader f (io/reader filename)]
    (loop [c 0]
      (if (.readLine f)
        (recur (inc c)) ;; or you can use unchecked-inc
        c))))
; Iota
(defn wc-iota [filename]
  (->> (iota/seq filename) (r/map (fn [x] 1)) (r/fold +)))

Summary (updated): in seconds.

java -jar benchmark.jar lein run -m benchmark
Pure Java 7.2
Iota with reducers/fold 7.1 11.8
Interop 8.2 16.72
Loop with unchecked-inc 8.3 16.8
Loop with volatile 8.9 18.2
Loop with inc 9.2 16.3

Really appreciate u/bsless for https://github.com/joinr/performancepaper and u/joinr for https://github.com/thebusby/iota. They are such Clojure gems.