我有一个函数foo:
(defn foo [a b] (* a b)) ; <- 2 ms per 10K
(foo 3 8) ; <- 24
我希望能够传递代理,原子或引用。
(defn bar [a b] (* @a @b)) ; <- 3.5 ms per 10K
但那么混合文字和代理呢?
(defn aref? [x] (isa? (class x) clojure.lang.ARef))
(defn foo [a b] (let [a (if (aref? a) @a a)
b (if (aref? b) @b b)]
(* a b))
(def x (ref 3))
(def y (ref 8))
(foo 3 8); <- 120 ms per 10K
(foo 3 y); <- 71 ms per 10K
(foo x 8); <- 73 ms per 10K
(foo x y); <- 6 ms per 10K
但那些是真正时髦的运行时间。我尝试更改foo
中分支的顺序,这显然与它无关。为什么我的新foo
评估文字的时间要比ARefs长20倍?
答案 0 :(得分:3)
实际上,ez121sl提到性能差异来自isa?
的使用。查看其源代码,您会发现它使用内置的global-hierarchy
(如果没有提供)并递归检查bases
类的child
(基类)是否存在是定义的parent
类。
使用instance?
(使用封面后面的Java instanceof?
)会产生更明智的时间。
(defn aref? [x]
(instance? clojure.lang.ARef x))
(defn foo [a b] (let [a (if (aref? a) @a a)
b (if (aref? b) @b b)]
(* a b)))
(def a (ref 3))
(def b (ref 8))
(time (dotimes [i 10000] (foo a b))) ; ~ 9ms
(time (dotimes [i 10000] (foo a 8))) ; ~ 2.7ms
(time (dotimes [i 10000] (foo 3 b))) ; ~ 2.7ms
(time (dotimes [i 10000] (foo 3 8))) ; ~ 1.7ms