Clojure中多方法与cond的表现

use*_*545 0 clojure

多方法比协议慢,应该尝试使用协议来解决问题,即使使用多方法提供了更灵活的解决方案.那么多方法是怎么回事cond?它们可以用来解决同样的问题,但我的猜测是多方法的性能开销很大cond.如果是这样,我为什么要使用多方法而不是cond

Dan*_*ton 7

多方法允许开放式扩展; 其他人可以在任意表达式上扩展你的多方法调度.Cond表达式被其他人甚至您自己的代码关闭以扩展.

如果你只是想对条件逻辑采取行动,那么cond就是你要走的路.如果您想要进行更复杂的调度,或者对具有不同行为的多种类型的数据应用函数,那么多方法可能更合适.


mav*_*ozo 6

你可以测量时为什么担心?

这是使用标准库的基准样本.CondMulti-methods代码取自http://blog.8thlight.com/myles-megyesi/2012/04/26/polymorphism-in-clojure.html.

警告这只是进行基准比较multimethodcond性能的一个示例.下面的结果 - 显示cond表现优于multimethod,不能推广到实践中的各种用法.您可以将此基准测试方法用于您自己的代码.

;; cond
(defn convert-cond [data]
   (cond
     (nil? data)
       "null"
     (string? data)
       (str "\"" data "\"")
     (keyword? data)
       (convert-cond (name data))
     :else
     (str data)))


(bench (convert-cond "yolo"))

Evaluation count : 437830380 in 60 samples of 7297173 calls.

             Execution time mean : 134.822430 ns
    Execution time std-deviation : 1.134226 ns
   Execution time lower quantile : 133.066750 ns ( 2.5%)
   Execution time upper quantile : 137.077603 ns (97.5%)
                   Overhead used : 1.893383 ns

Found 2 outliers in 60 samples (3.3333 %)
    low-severe   2 (3.3333 %)
 Variance from outliers : 1.6389 % Variance is slightly inflated by outliers

;; multimethod
(defmulti convert class)

(defmethod convert clojure.lang.Keyword [data]
  (convert (name data)))

(defmethod convert java.lang.String [data]
   (str "\"" data "\""))

(defmethod convert nil [data]
   "null")

 (defmethod convert :default [data]
   (str data))

(bench (convert "yolo"))
Evaluation count : 340091760 in 60 samples of 5668196 calls.

             Execution time mean : 174.225558 ns
    Execution time std-deviation : 1.824118 ns
   Execution time lower quantile : 170.841203 ns ( 2.5%)
   Execution time upper quantile : 177.465794 ns (97.5%)
                   Overhead used : 1.893383 ns
nil

  • 你不应该相信这个基准 - 你只转换一种类型,导致两种情况下的最佳代码路径(多方法中的单态调用站点).最好使用随机混合的输入类型进行测试(理想情况下匹配实际代码中的情况). (6认同)