Clojure代码的时序分析

end*_*gin 3 clojure

你好Clojure专家,

我正在尝试在Clojure 1.3中进行一些计时测试,我想我会问一个基于现有代码的问题,该代码解决了从这篇博文中改编的微分方程.

代码如下:

;; the differential equation is                                                                                            
;; dy/dt = f(y,t) = t - y                                                                                                  

(defn f [t y] (- t y))

;; solve using Euler's method                                                                                              
(defn solveEuler [t0 y0 h iter]
  (if (> iter 0)
    (let [t1 (+ t0 h)
          y1 (+ y0 (* h (f t0 y0)))]
      (recur t1 y1 h (dec iter)))
    [t0 y0 h iter]))

(defn multipleSolveEuler []
  (let [steps '(1 10 100 1000 10000 100000)
        results (map #(second (solveEuler 0.0 0.0 (/ 1.0 %) %)) steps)
        errors  (map #(- (Math/exp -1) %) results)]
    (partition 3 (interleave steps results errors))))

(def *cpuspeed* 2.0)

(defmacro cyclesperit [expr its]
  `(let [start# (. System (nanoTime))
         ret# ( ~@expr (/ 1.0 ~its) ~its )
         finish# (. System (nanoTime))]
     (int (/ (* *cpuspeed* (- finish# start#)) ~its))))

(defn solveEuler-2 [t0 y0 h its]
  (let [zero (int 0)]
    (loop [t0 (double t0), y0 (double y0), h (double h), its (int its)]
      (if (> its zero)
        (let [t1 (+ t0 h)
              y1 (+ y0 (* h (- t0 y0)))]
          (recur t1 y1 h (dec its)))
        [t0 y0 h its]))))
Run Code Online (Sandbox Code Playgroud)

所以,当我说

(time solveItEuler-2 0.0 1.0 (/ 1.0 1000000000) 1000000000))
Run Code Online (Sandbox Code Playgroud)

我在一个6个月大的Macbook pro上得到6004.184毫秒的时间.我再次发出命令,我在同一时间.但是当我再运行3次时,我得到3500毫秒的时间.我之前已经注意到了其他代码片段,并且想知道为什么会这样.我想我会期望在连续运行中执行时间大致相似.

难道我缺乏理解"时间"是如何工作的,我缺少的东西,或者引擎盖下发生的某种缓存?

谢谢.

Ale*_*art 7

这不是time相关的,而是JVM在运行时优化代码.你观察到的是典型的; 执行时间将下降,然后在大约3次调用后稳定下来.

  • @Yehonathan [One ref](http://www.bestinclass.dk/index.php/2010/02/benchmarking-jvm-languages/).[anoth](http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java).你想搜索"JVM热身","热点内联",-XX:MaxInlineSize" (2认同)

小智 7

我建议使用Criterium库进行基准测试.它旨在处理在JVM上运行的基准测试代码的缺陷.