문제
왜 감속기 라이브러리에 매핑 / 감소가 정상 맵 / 축소보다 더 나쁜 성능을 갖고 있습니까?
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)))
...
.
감속기는 정상적인 감소가있는 동안 게으른 목록에서 실제로 잘 작동하지 않습니다.
실제 이익을 얻으려면 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