Clojure 计算文件夹大小

Clojure 计算文件夹大小,clojure,agent,Clojure,Agent,我正在尝试并行计算文件夹大小。 也许这是幼稚的做法。 我所做的是,将每个分支节点(目录)的计算交给代理。 所有叶节点都将其文件大小添加到“我的大小”。 嗯,它不起作用。:) “扫描”可以连续正常工作。 “pscan”仅打印第一级的文件 (def agents (atom [])) (def my-size (atom 0)) (def root-dir (clojure.java.io/file "/")) (defn scan [listing] (doseq [f listing]

我正在尝试并行计算文件夹大小。 也许这是幼稚的做法。 我所做的是,将每个分支节点(目录)的计算交给代理。 所有叶节点都将其文件大小添加到“我的大小”。 嗯,它不起作用。:)

“扫描”可以连续正常工作。 “pscan”仅打印第一级的文件

(def agents (atom []))
(def my-size (atom 0))
(def root-dir (clojure.java.io/file "/"))

(defn scan [listing]
  (doseq [f listing]
    (if (.isDirectory f)
      (scan (.listFiles f))
      (swap! my-size #(+ % (.length f))))))

(defn pscan [listing]
  (doseq [f listing]
    (if (.isDirectory f)
      (let [a (agent (.listFiles f))]
        (do (swap! agents #(conj % a))
            (send-off a pscan)
            (println (.getName f))))
    (swap! my-size #(+ %  (.length f))))))
你知道我做错了什么吗


谢谢。

无需使用原子保持状态。纯功能性:

(defn psize [f]
  (if (.isDirectory f)
    (apply + (pmap psize (.listFiles f)))
    (.length f)))
所以并行计算文件大小应该很容易? 不是:)

我试图更好地解决这个问题。我意识到我正在执行阻塞I/O操作,因此pmap无法完成这项工作。 我在想,也许将大量目录(分支)交给代理独立处理会有意义。看起来是这样的:) 嗯,我还没有对它进行基准测试

它可以工作,但是,在类UNIX系统上使用符号链接可能会有一些问题

(def user-dir (clojure.java.io/file "/home/janko/projects/"))
(def root-dir (clojure.java.io/file "/"))
(def run? (atom true))
(def *max-queue-length* 1024)
(def *max-wait-time* 1000)    ;; wait max 1 second then process anything left
(def *chunk-size* 64)
(def queue (java.util.concurrent.LinkedBlockingQueue. *max-queue-length* ))
(def agents (atom []))
(def size-total (atom 0))
(def a (agent []))

(defn branch-producer [node]
  (if @run?
    (doseq [f node]
      (when (.isDirectory f)
    (do (.put queue f)
        (branch-producer (.listFiles f)))))))

(defn producer [node]
  (future
    (branch-producer node)))

(defn node-consumer [node]
  (if (.isFile node)
    (.length node)
    0))

(defn chunk-length []
  (min (.size queue) *chunk-size*))

(defn compute-sizes [a]
  (doseq [i (map (fn [f] (.listFiles f)) a)]
    (swap! size-total #(+ % (apply + (map node-consumer i))))))

(defn consumer []
  (future
    (while @run?
      (when-let [size (if (zero? (chunk-length))
            false
            (chunk-length))] ;appropriate size of work
      (binding [a (agent [])]                    
        (dotimes [_ size]         ;give us all directories to process
          (when-let [item (.poll queue)]
            (set! a (agent (conj @a item)))))
        (swap! agents #(conj % a))
        (send-off a compute-sizes))
      (Thread/sleep *max-wait-time*)))))
你可以通过打字开始

    (producer (list user-dir))
    (consumer)
对于结果类型

    @size-total
你可以通过(有正在运行的期货-如果我错了,请纠正我)来阻止它


如果您发现任何错误,欢迎分享您的想法

新手在做lisp/clojure时是一种永久的心态;)谢谢,呃,这有点鼓舞人心。但当你阅读clojure/docs时,你会发现“pmap”是“……只对计算密集型函数有用,其中f的时间占协调开销的主导地位。”从我的观点来看,计算文件夹大小的解决方案更像是生产者/消费者的问题。当生产者将根目录切片到分支节点时,消费者计算这些分支的文件大小。这更多的是设置正确的问题大小。我受到另一个固定的启发,开始使用clojure 1.6.0、leiningen 2.5.0和runnable二进制文件。
    (swap! run? not)