由向量/chunked-seqs构建的lazy-seqs有时会进行缓慢的首次/后续reduce。
观察
`
(def xs (vec (range 3000000)))
(time (reduce max xs)) ;; #1: 130ms, (参考)
(time (reduce max (lazy-cat xs))) ;; #2: 130ms,同样的速度
(time (reduce max 0 (lazy-cat xs))) ;; #3: 500ms,慢4倍!!
;; 使用concat加倍,它们的速度不会慢2倍,而是慢10倍
(time (reduce max (lazy-cat xs xs))) ;; #4: 1200ms
(time (reduce max 0 (lazy-cat xs xs))) ;; #5: 1200ms
`
关于#3的解释:问题在于,当使用init调用{{seq-reduce}}时,它将不会逃逸到更快的reduce路径,而会坚持首次/后续。
注意:在Clojure中,他们正确地缩放(前3个约为45ms,最后2个约为110ms)。
原因在于Clojure正确地逃逸到快速路径
https://github.com/clojure/clojure/blob/2b242f943b9a74e753b7ee1b951a8699966ea560/src/clj/clojure/core/protocols.clj#L131-L143
这是一个RFC,因为我并不完全确定关于实现的细节。需要小心不要压碎堆栈...
问题
1. ChunkedCons应该实现IReduce?我认为是的。