chu*_*nsj 1 performance clojure
我有一个在Lisp(SBCL)中实现的版本,在0.001秒内运行12个样本.然而,这个版本(在clojure中)需要超过1.1秒.我应该怎么做才能让这个代码像原始的Lisp版本一样快速运行?
为了确保,我的数字不包括启动repl和其他人的时间.并且是从sbcl和clojure的时间函数.(是的,我的笔记本电脑是相当旧的原子为基础的)
而且这个应用程序将用于repl,而不是在单个应用程序中编译,因此在基准测试之前运行一千次似乎没有意义.
哦,fbars是这样的:[[10.0 10.5 9.8 10.1] [10.1 10.8 10.1 10.7] ...],这是股票的开盘 - 高 - 低 - 收盘价格柱.
(defn- build-new-smpl [fmx fmn h l c o]
(let [fmax (max fmx h)
fmin (min fmn l)
fc (/ (+ c fmax fmin) 3.0)
fcd (Math/round (* (- fc o) 1000))
frd (Math/round (* (- (* 2.0 c) fmax fmin) 1000))]
(if (and (> fcd 0) (> frd 0))
[1 fmax fmin]
(if (and (< fcd 0) (< frd 0))
[-1 fmax fmin]
[0 fmax fmin]))))
(defn binary-smpls-using [fbars]
(let [fopen (first (first fbars))]
(loop [fbars fbars, smpls [], fmax fopen, fmin fopen]
(if (> (count fbars) 0)
(let [bar (first fbars)
[_ h l c _] bar
[nsmpl fmx fmn] (build-new-smpl fmax fmin h l c fopen)]
(recur (rest fbars) (conj smpls nsmpl) fmx fmn))
smpls))))
Run Code Online (Sandbox Code Playgroud)
================================================
谢谢.我设法将1000次迭代的差异设为0.5秒(SBCL为1.3秒,Clojure为1.8秒).主要因素是我应该创建fbars不是懒惰但是作为具体(?)向量或数组,这解决了我的问题.
您需要使用适当的基准测试库; 标准的Clojure解决方案是Hugo Duncan的Criterium.
原因是JVM上的代码开始以解释模式运行,然后最终由JIT编译器编译; 它是JIT编译之后的稳态行为,您希望在分析阶段进行基准测试而不是行为.然而,这是非常棘手的,因为JIT编译器可以在无法操作的地方优化无操作,因此您需要确保您的代码导致无法优化的副作用,但是您仍然需要运行它在循环中获得有意义的结果等 - 快速和肮脏的解决方案只是不削减它.(请参阅Elliptic Group,Inc.Java基准测试文章,该文章也与Criterium的README相关联,以便对所涉及的问题进行扩展讨论.)
循环在长度为1000的向量中列出的两个样本,在我的机器上的Criterium基准测试中得到~327μs的时间:
(require '[criterium.core :as c])
(def v (vec (take 1000 (cycle [[10.0 10.5 9.8 10.1] [10.1 10.8 10.1 10.7]]))))
(c/bench (binary-smpls-using v))
WARNING: Final GC required 4.480116525558204 % of runtime
Evaluation count : 184320 in 60 samples of 3072 calls.
Execution time mean : 327.171892 µs
Execution time std-deviation : 3.129050 µs
Execution time lower quantile : 322.731261 µs ( 2.5%)
Execution time upper quantile : 333.117724 µs (97.5%)
Overhead used : 1.900032 ns
Found 1 outliers in 60 samples (1.6667 %)
low-severe 1 (1.6667 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
Run Code Online (Sandbox Code Playgroud)
一个非常好的基准实际上会涉及一个有趣的数据集(所有不同的样本,最好来自现实世界).