Clojure的pmap函数为URL提取操作产生了多少个线程?

dan*_*dan 21 concurrency clojure pmap

关于该pmap函数的文档让我想知道如何通过Web获取XML提要集合的效率.我不知道pmap会产生多少并发获取操作以及最大值.

Ale*_*ler 21

如果您检查来源,您会看到:

> (use 'clojure.repl)
> (source pmap)
(defn pmap
  "Like map, except f is applied in parallel. Semi-lazy in that the
  parallel computation stays ahead of the consumption, but doesn't
  realize the entire result unless required. Only useful for
  computationally intensive functions where the time of f dominates
  the coordination overhead."
  {:added "1.0"}
  ([f coll]
   (let [n (+ 2 (.. Runtime getRuntime availableProcessors))
         rets (map #(future (f %)) coll)
         step (fn step [[x & xs :as vs] fs]
                (lazy-seq
                 (if-let [s (seq fs)]
                   (cons (deref x) (step xs (rest s)))
                   (map deref vs))))]
     (step rets (drop n rets))))
  ([f coll & colls]
   (let [step (fn step [cs]
                (lazy-seq
                 (let [ss (map seq cs)]
                   (when (every? identity ss)
                     (cons (map first ss) (step (map rest ss)))))))]
     (pmap #(apply f %) (step (cons coll colls))))))
Run Code Online (Sandbox Code Playgroud)

(+ 2 (.. Runtime getRuntime availableProcessors))是一个很大的线索.pmap将抓取第一(+ 2 processors)部分工作并通过异步运行它们future.因此,如果你有2个核心,它将一次启动4个工作,试图保持领先于你,但最大应该是2 + n.

future最终使用代理I/O线程池,它支持无限数量的线程.它会随着工作的增加而增长,如果线程未被使用则会缩小.

  • 那么并发性从来都不是一个简短的答案.:)我说pmap实际上并不适合这个用例.你真的想要并行地等待所有*的源 - 在上面的情况下,pmap会延迟启动第5个.除非您不一定想要了解所有来源,在这种情况下,pmap的懒惰行为是好的.我会想你的东西改为映射来源并使用future来发出每个请求. (5认同)
  • 我可能错了,但问题可能是n + 2线程将阻止等待Web响应.因此,您无法获得足够的最大吞吐量请求--pmap实际上是针对CPU绑定的工作负载.如果发生这种情况,那么您可以在将来打包每个请求呼叫,它们将立即全部飞出. (4认同)
  • 简而言之,"pmap"非常适合发送大量网络电话和处理响应吗?有什么警告吗? (2认同)

mik*_*era 11

基于Alex的优秀答案,解释了pmap如何工作,这是我对你的情况的建议:

(doall
  (map
    #(future (my-web-fetch-function %))
    list-of-xml-feeds-to-fetch))
Run Code Online (Sandbox Code Playgroud)

理由:

  • 您需要尽可能多的工作,因为大多数会阻止网络IO.
  • Future将为每个请求启动一个异步工作,在线程池中处理.你可以让Clojure聪明地处理它.
  • 地图上的doall将强制评估完整序列(即所有请求的启动).
  • 您的主线程可以立即开始取消引用期货,因此可以在个别结果回来时继续取得进展