2

我正在为 Clojure 中的程序编写基准测试。我有n线程同时访问缓存。每个线程将访问缓存x时间。每个请求都应该记录在一个文件中。

为此,我创建了一个代理来保存要写入的文件的路径。当我想编写 send-off一个写入文件并简单地返回路径的函数时。这样我的文件写入是无竞争条件的。

当我在没有代理的情况下执行我的代码时,它会在几毫秒内完成。当我使用代理时,每次我的代码运行速度非常慢时都要求每个线程发送给代理。我说的是分钟。

(defn load-cache-only [usercount cache-size]
  "Test requesting from the cache only."
  ; Create the file to write the benchmark results to.
  (def sink "benchmarks/results/load-cache-only.txt")
  (let [data-agent (agent sink)
        ; Data for our backing store generated at runtime.
        store-data (into {} (map vector (map (comp keyword str)
                                             (repeat "item") 
                                             (range 1 cache-size)) 
                                        (range 1 cache-size)))
        cache      (create-full-cache cache-size store-data)]
    (barrier/run-with-barrier (fn [] (load-cache-only-work cache store-data data-agent)) usercount)))

(defn load-cache-only-work [cache store-data data-agent]
  "For use with 'load-cache-only'. Requests each item in the cache one.
   We time how long it takes for each request to be handled."
  (let [cache-size  (count store-data)
        foreachitem (fn [cache-item]
                      (let [before  (System/nanoTime)
                            result  (cache/retrieve cache cache-item)
                            after   (System/nanoTime)
                            diff_ms ((comp str float) (/ (- after before) 1000))]
                        ;(send-off data-agent (fn [filepath] 
                                           ;(file/insert-record filepath cache-size diff_ms)
                                           ;filepath))
                        ))]
    (doall (map foreachitem (keys store-data)))))

(barrier/run-with-barrier)代码只是产生usercount多个线程并同时启动它们(使用原子)。我传递的函数是每个线程的主体。

正文将简单地映射到一个名为 的列表store-data,这是一个键值列表(例如,{:a 1 :b 2}。我的代码中这个列表的长度现在是 10。用户数也是 10。

如您所见,代理发送的代码已被注释掉。这使得代码正常执行。但是,当我启用发送时,即使没有写入文件,执行时间也太慢了。

编辑:

我制作了每个线程,在他发送给代理之前,打印一个点。这些点的出现速度与没有发送时一样快。所以最后一定有什么东西阻塞了。

难道我做错了什么?

4

1 回答 1

5

(shutdown-agents)如果您希望 JVM 在合理的时间内退出,您需要在完成向代理发送内容后调用。

潜在的问题是,如果您不关闭代理,支持其线程池的线程将永远不会关闭,并阻止 JVM 退出。如果没有其他东西在运行,有一个超时将关闭池,但它相当长。完成生成操作后立即调用shutdown-agents将解决此问题。

于 2014-05-02T14:02:28.953 回答