문제

왜 감속기 라이브러리에 매핑 / 감소가 정상 맵 / 축소보다 더 나쁜 성능을 갖고 있습니까?

user=> (time (reduce + (map inc (range 100000000))))
"Elapsed time: 14412.627966 msecs"
5000000050000000

user=> (time (reduce + (r/map inc (range 100000000))))
... (C-c)

user=> (time (r/reduce + (r/map inc (range 100000000))))
....(C-c)
.

나는 두 번의 두 번 죽이는 것이 무기한으로 오래 걸립니다.여기 틀린 것은 무엇입니까?

편집 : 다른 언어가 비슷한 문제가있는 것처럼 보입니다.스칼라는 백만 명이 속 어울리는 것 같습니다. Scala 병렬 컬렉션이 때때로 OutOfMemoryError를 일으키는 이유는 무엇입니까? ...에Clojure Decepers는 백만 명이 정상보다 빠릅니다.

도움이 되었습니까?

해결책

보완 @ a-webb의 답변을 보완하십시오. 이것은 컴파일러 버그이며 실제로 고쳐주는 관련이 있습니다.( 자세한 내용은이 게시물을 참조하십시오.)

문제를 해결하는 또 다른 방법은 fuse 을 사용하는 것입니다.

(defn once-seq
  "Returns a sequence on which seq can be called only once."
  [coll]
  (let [a (atom coll)]
    (reify clojure.lang.Seqable
      (seq [_]
        (let [coll @a]
          (reset! a nil)
          (seq coll))))))
.

및 다음 :

=> (time (r/reduce + (r/map inc (once-seq (range 100000000)))))
"Elapsed time: 3692.765 msecs"
5000000050000000
.

다른 팁

성능은 메모리가 소모 될 때 정지로 그라인딩하는 것입니다.기다리고 있으면 메모리 오류가 발생할 가능성이 큽니다.감속기를 만드는 것은 컬렉션의 머리를 폐쇄로 유지합니다.따라서 거대한 게으른 시퀀스는 실현 될 때 메모리를 묶습니다.

여기에 일어나고있는 일이 발생하고 증류가 발생합니다

user=> (def n 100000000)
#'user/n

user=> (time (dorun (range n)))
"Elapsed time: 12349.034702 msecs"
.

이제는 동일하지만 폐쇄 내에서

user=> (defn foo [x] (fn [f] (f x)))
#'user/foo

user=> (time ((foo (range n)) dorun))
OutOfMemoryError GC overhead limit exceeded ... (sometime later)
.

와 비교합니다
(time (do (doall (range n)) nil))
OutOfMemoryError GC overhead limit exceeded ... (sometime later)
.

감속기의 용의자 폐쇄

user=> (source r/folder)
(defn folder
  "Given a foldable collection, [...]"
  {:added "1.5"}
  ([coll xf]
     (reify
      clojure.core.protocols/CollReduce
      (coll-reduce [_ f1]
                   (clojure.core.protocols/coll-reduce coll (xf f1) (f1)))
   ...
.

Christophe Grand 게으른 방식으로 감속기를 구성하는 방법에 대한 멋진 게시물

감속기는 정상적인 감소가있는 동안 게으른 목록에서 실제로 잘 작동하지 않습니다.

실제 이익을 얻으려면 Laughers가 아닌 컬렉션이 필요합니다.벡터가 있고 줄이는 대신 접기를 사용해야합니다.

 (def v (into [] (range 10000000)))
 (time (reduce + (map inc v)))
 ;; "Elapsed time: 896.79 msecs"
 (time (reduce + (r/map inc v)))
 ;; "Elapsed time: 671.947 msecs" 
 (time (r/fold + (r/map inc v)))
 ;; "Elapsed time: 229.45 msecs"
.

감속기는 큰 덩어리가 필요한 포크 / 가입 프레임 워크와 함께 작동합니다.게으른 (chunked) 시퀀스 에서이 큰 덩어리가 없으므로 포크 / 가입이 잘 작동 할 수 없습니다.

Redueers는 https://vimeo.com/45561411

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top