- tnoda-clojure • Crunching Numbers with Clojure - 11 Tips to Boost Your Performance
- clojurewest2012-slides/Solano-Gómez-Crunching-Numbers-with-Clojure.pdf at master · strangeloop/clojurewest2012-slides · GitHub
個人的にはコレクションと配列との使用メモリ量比較が参考になりました.1M 個の long を格納するとして,vector だと 30MB, vector-of だと 9MB, 配列だと 8MB というのは覚えておいて損は無さそうです.案外 vector はメモリを食いません.
(defn current-total-memory-usage []
(System/gc)
(- (.. Runtime getRuntime totalMemory)
(.. Runtime getRuntime freeMemory)))
(defmacro memory-usage [& exprs]
`(let [pre# (current-total-memory-usage)]
~@exprs
(double (/ (- (current-total-memory-usage) pre#) 1024))))
type hintsが足りていないものをlein check
で教えてくれるようにするために、project.clj
に以下を追加しておくとよい。
:global-vars {*warn-on-reflection* true}
なお、マクロの中でtype hintsが付けにくい、などの場合はtype hintsの部分のみを取り出した補助関数を作成するとよい。
clojure.core/time
の出力が分かりにくいにので、人間にとって分かりやすいフォーマットで出力するマクロを書いてみた。
(defn conv-time-to-easily-understandable-time-format
"(-> (+ 83.0 (* 5 60 60)) conv-time-to-easily-understandable-time-format)
=> 5 hours 1 minutes 23.000 seconds"
[t]
(let [[hour r0] ((juxt quot rem) t (* 60 60))
[minute r1] ((juxt quot rem) r0 (* 60))]
(->> [(int hour) "hours"
(int minute) "minutes"
(format "%3.3f" r1) "seconds"]
(interpose \space)
(apply str))))
(defmacro easily-understandable-time
"(easily-understandable-time (Thread/sleep 1000))
\"Elapsed time: 0 hours 0 minutes 1.001 seconds\"
nil"
[expr]
`(let [start# (. System (nanoTime))
ret# ~expr
result# (/ (double (- (. System (nanoTime)) start#)) 1000000.0)]
(->> (/ result# 1000)
(conv-time-to-easily-understandable-time-format)
(str "Elapsed time: ")
(prn))
ret#))
何度も呼び出される関数などで可変長引数を利用していると速度が遅くなる場合がある。引数が4、5個くらいであればそれぞれ展開したものを用意しておくと速度が改善される場合がある。