2014-12-05 7 views
1

모두 아래 기능 (SQRT n)도 2에서 이동, n은 비 프라임 경우 모두성능 차이

(defn is-prime-for? [n] 
    (empty? (for [i (range 2 (math/sqrt (inc n))) 
       :when (= 0 (rem n i))] 
      i))) 

(defn is-prime-loop? [n] 
    (loop [i 2] 
    (cond (> i (math/sqrt (inc n))) true 
      (zero? (rem n i)) false 
      :else (recur (inc i))))) 

그런 다음 즉시 감지 될 때 중지 왜 우리는 그 대폭적인 성능 차이를 보입니까? 은 "루프"버전은

project-euler.prob010> (time (dorun (map is-prime-for? (range 200000)))) 
"Elapsed time: 3267.613099 msecs" 
;; => nil 
project-euler.prob010> (time (dorun (map is-prime-loop? (range 200000)))) 
"Elapsed time: 12961.190032 msecs" 
;; => nil 
+0

하나는 equals를 사용하고 다른 하나는 0을 사용합니까? 술부. 그래서 그것은 다른 하나의 것입니다. – RedDeckWins

답변

7

이러한 마이크로 벤치 마크는 특정 부분의 성능에 영향을 미칠 수있는 다양한 요인에 대해 그들이 고려하지 않기 때문에 일반적으로 의미가 있습니다 (바탕 화면에) 많은 시간이 거의 4 시간 소요 (예 : JVM 준비, 최적화 ...). 신뢰할 수있는 결과를 얻으려면 criterium과 같은 벤치마킹 라이브러리를 사용해야합니다.

은 두 가지 버전이 결과에 반영됩니다 몇 가지 중요한 차이가 말했다되는 :

  • for 누구의 유지 보수 비용 loop/recur에서 수행되는 것보다 더 높은 게으른 시퀀스를 생성한다.
  • loop 버전은 모든 반복에서 (Math/sqrt (inc n))을 계산하고 for 버전은 한 번만 계산합니다.
  • zero?은 간접 지정의 한 수준이 (= 0 ...) 이상입니다.

분명히 컴파일러가이를 최적화 할 수는 있지만 결과 (Java 버전, OpenJDK와 Oracle, Clojure 버전 등)를 변경할 수있는 요소가 더 많습니다. 그래서, 오라클 JDK 1.7.0_67에 Clojure의 1.6.0를 사용하여 내 벤치 마크 실행의 여기 결과 :

(criterium.core/quick-bench (mapv is-prime-for? (range 200000))) 
Evaluation count : 6 in 6 samples of 1 calls. 
      Execution time mean : 1.942423 sec 
    Execution time std-deviation : 36.768207 ms 
    Execution time lower quantile : 1.912171 sec (2.5%) 
    Execution time upper quantile : 1.984463 sec (97.5%) 
        Overhead used : 8.986692 ns 

(criterium.core/quick-bench (mapv is-prime-loop? (range 200000))) 
Evaluation count : 6 in 6 samples of 1 calls. 
      Execution time mean : 724.077492 ms 
    Execution time std-deviation : 5.695680 ms 
    Execution time lower quantile : 716.547992 ms (2.5%) 
    Execution time upper quantile : 730.173992 ms (97.5%) 
        Overhead used : 8.986692 ns 

그래서, 내 컴퓨터에서 loop 버전은 for보다 약 3 배 빠르다.

+1

감사! 나는 이해하고 비슷한 결과를 관찰 –

+0

또한 [criterium] (https://github.com/hugoduncan/criterium)에 대한 포인터 감사합니다. –