如何使用Tufte分析多线程clojure结果

如何使用Tufte分析多线程clojure结果,clojure,profiling,Clojure,Profiling,是一个分析库,非常适合理解运行时的组成,特别是在复杂的调用堆栈中 当我在我的项目中运行它时,我认为性能昂贵的一段代码没有在结果中注册为高违规者,这导致发现Tufte(合理地)只捕获了线程本地结果 文档表明,它使用{:dynamic?true}选项内置绑定到其他线程上的仪器累计时间,但似乎需要更多的绑定来捕获其他线程上的累计时间,例如由pmap启动的线程 下面是最初的Tufte演示,介绍了一些多线程: (require '[taoensso.tufte :as tufte :refer (defn

是一个分析库,非常适合理解运行时的组成,特别是在复杂的调用堆栈中

当我在我的项目中运行它时,我认为性能昂贵的一段代码没有在结果中注册为高违规者,这导致发现Tufte(合理地)只捕获了线程本地结果

文档表明,它使用
{:dynamic?true}
选项内置绑定到其他线程上的仪器累计时间,但似乎需要更多的绑定来捕获其他线程上的累计时间,例如由
pmap
启动的线程

下面是最初的Tufte演示,介绍了一些多线程:

(require '[taoensso.tufte :as tufte :refer (defnp p profiled profile)])

;; We'll request to send `profile` stats to `println`:
(tufte/add-basic-println-handler! {})

;;; Let's define a couple dummy fns to simulate doing some expensive work
(defn get-x [] (Thread/sleep 500)             "x val")
(defn get-y []
  (pmap
    #(do
        (Thread/sleep 500)
        (print %))
    (range 10)))

;; How do these fns perform? Let's check:

(profile ; Profile any `p` forms called during body execution
  {:dynamic? true} ; Profiling options; we'll use the defaults for now
  (dotimes [_ 5]
    (p :get-x (get-x))
    (p :get-y (get-y))))
输出表明println语句强制线程求值。然而,get-y累计时间并未显示在结果中:

2187306594=> nil
=> #{:basic-println}
=> #'user/get-x
=> #'user/get-y
8904365271703695842110783956243415760829=> nil

       pId      nCalls       Min        Max       MAD      Mean   Time% Time
    :get-x           5  500.52ms   504.84ms    1.44ms  502.44ms     100 2.51s
    :get-y           5   90.67μs   581.91μs   162.2μs  269.29μs       0 1.35ms
Clock Time                                                          100 2.51s
Accounted Time                                                      100 2.51s

答:延迟初始化。虽然数据被打印到了屏幕上,但在spied on表单
get-y
之外,是
(profile…
表单的末尾在执行此操作

这将产生同样的效果:

(profile ; Profile any `p` forms called during body execution
  {:dynamic? true} ; Profiling options; we'll use the defaults for now
  (dotimes [_ 5]
    (p :get-x (get-x))
    (doall (p :get-y (get-y)))))

30167894521045768392530798241651268940371023657894=> nil

           pId      nCalls       Min        Max       MAD      Mean   Time% Time
        :get-x           5  500.07ms   504.58ms    1.41ms  503.08ms      50 2.52s
        :get-y           5   80.25μs   126.18μs   15.98μs  104.84μs       0 524.18μs
    Clock Time                                                          100 5.03s
Accounted Time                                                           50 2.52s
而这一个实现了get-y配置文件中的惰性序列:

(profile ; Profile any `p` forms called during body execution
  {:dynamic? true} ; Profiling options; we'll use the defaults for now
  (dotimes [_ 5]
    (p :get-x (get-x))
    (p :get-y (doall (get-y)))))

12037645987105892436354169872031089546721058729634=> nil

           pId      nCalls       Min        Max       MAD      Mean   Time% Time
        :get-x           5  502.54ms   504.71ms   705.6μs   503.5ms      50 2.52s
        :get-y           5  501.69ms   505.68ms    1.05ms  503.06ms      50 2.52s
    Clock Time                                                          100 5.03s
Accounted Time                                                          100 5.03s
对于评测体验,这一点很重要,因为在处理惰性序列时,您将了解它们的使用性能,而不是序列本身:

(profile ; Profile any `p` forms called during body execution
  {:dynamic? true} ; Profiling options; we'll use the defaults for now
  (dotimes [_ 5]
    (p :get-x (get-x))
    (p ::realize-y
       (doall (p :get-y (get-y))))))

06538947123410695278450678913223071958645126380479=> nil

            pId      nCalls       Min        Max       MAD      Mean   Time% Time
:user/realize-y           5  503.29ms   504.86ms  458.12μs  504.37ms      50 2.52s
         :get-x           5  500.13ms   505.06ms     1.4ms  503.64ms      50 2.52s
         :get-y           5    86.0μs     1.15ms  331.81μs  322.94μs       0 1.61ms
     Clock Time                                                          100 5.04s
 Accounted Time                                                          100 5.04s