# メモリ - [tnoda-clojure • Crunching Numbers with Clojure - 11 Tips to Boost Your Performance](http://tnoda-clojure.tumblr.com/post/28924516585/crunching-numbers-with-clojure-11-tips-to-boost-your) - [clojurewest2012-slides/Solano-Gómez-Crunching-Numbers-with-Clojure.pdf at master · strangeloop/clojurewest2012-slides · GitHub](https://github.com/strangeloop/clojurewest2012-slides/blob/master/Solano-G%C3%B3mez-Crunching-Numbers-with-Clojure.pdf) > 個人的にはコレクションと配列との使用メモリ量比較が参考になりました.1M 個の long を格納するとして,vector だと 30MB, vector-of だと 9MB, 配列だと 8MB というのは覚えておいて損は無さそうです.案外 vector はメモリを食いません. ## メモリ消費量を測定する用のマクロ ```clj (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 type hintsが足りていないものを`lein check`で教えてくれるようにするために、`project.clj`に以下を追加しておくとよい。 ```clj :global-vars {*warn-on-reflection* true} ``` なお、マクロの中でtype hintsが付けにくい、などの場合はtype hintsの部分のみを取り出した補助関数を作成するとよい。 ## 補助マクロ `clojure.core/time`の出力が分かりにくいにので、人間にとって分かりやすいフォーマットで出力するマクロを書いてみた。 - [clj-utils/src/clj_utils/time.clj at master · syou6162/clj-utils · GitHub](https://github.com/syou6162/clj-utils/blob/master/src/clj_utils/time.clj) ```clj (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個くらいであればそれぞれ展開したものを用意しておくと速度が改善される場合がある。