Concurrency Clojure';是否为URL获取操作生成pmap函数?

Concurrency Clojure';是否为URL获取操作生成pmap函数?,concurrency,clojure,pmap,Concurrency,Clojure,Pmap,关于pmap函数的文档让我想知道,对于通过web获取XML提要集合这样的东西,它的效率有多高。我不知道pmap会产生多少并发获取操作,最大值是多少。如果您检查源代码,您会看到: > (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

关于
pmap
函数的文档让我想知道,对于通过web获取XML提要集合这样的东西,它的效率有多高。我不知道pmap会产生多少并发获取操作,最大值是多少。

如果您检查源代码,您会看到:

> (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))))))
(+2(…Runtime getRuntime availableProcessors))
是一条重要线索。pmap将获取第一批
(+2个处理器)
工件,并通过
未来
异步运行它们。因此,如果你有2个内核,它将一次启动4个工作,试图保持领先一点,但最大值应为2+n


future
最终使用代理I/O线程池,该线程池支持无限数量的线程。它将随着工作的进行而增长,如果线程未使用,它将收缩

基于Alex解释pmap工作原理的出色回答,以下是我对您的情况的建议:

(doall
  (map
    #(future (my-web-fetch-function %))
    list-of-xml-feeds-to-fetch))
理由:

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

    • 没有时间编写长响应,但是有一个clojure.contrib http代理,它将每个get/post请求创建为自己的代理。因此,您可以发出一千个请求,它们都将并行运行,并随着结果的出现而完成。

      查看pmap的操作,无论您拥有多少个处理器,它似乎一次运行32个线程,问题是map将比计算提前32个线程,未来将由它们自己启动。(样本)
      (defn samplef[n]
      (打印项次“开始”n)
      (线程/睡眠10000)
      n)
      (def结果(pmap样本(范围0-100)))

      );您将等待10秒钟,然后在拍摄第33张照片时看到32张照片,然后再拍摄其他32张照片 ; 打印一次执行32个并发线程的分钟数 ; 对我来说,这并不完美
      ; SALUDOS Felipe

      那么简短的回答是
      pmap
      对于发送大量网络呼叫和处理响应来说是完美的吗?有任何警告吗?我可能错了,但问题可能是n+2线程将阻止等待web响应。因此,您将无法获得足够的飞行中请求以获得最大吞吐量—pmap实际上是用于CPU受限的工作负载。如果这种情况发生在您身上,那么您可以在将来打包每个请求调用,它们将立即全部飞走我认为pmap实际上并不适合这个用例。您确实希望并行地等待所有源-在上述情况下,pmap将延迟启动第五个源。除非,否则您不一定要通过所有源代码,在这种情况下,pmap的懒惰行为是好的。我很想让你的东西映射到源代码上,并使用future来发出每个请求。我想知道为什么在pmap中没有添加
      fn
      参数,以不同的方式控制线程的数量(例如,对于每个工作线程消耗的内存是一个问题的情况,通常也是如此).我认为futures使用了一个无限线程池,因此在大量提要集合上运行此线程池可能会导致问题。此外,您可能希望再次将其映射到
      deref
      futures,以便知道什么时候一切都完成了。