2024年Clojure状态调查!中分享您的想法。

欢迎!请访问关于页面以获取有关如何工作的更多信息。

+13
协议
目前`satisfies?`没有使用协议方法使用的相同实现缓存,这使得它在实际应用中速度太慢。

使用

(defprotocol p (f [_]))
(deftype x [])
(deftype y [])
(extend-type x p (f [_]))


补丁前

(let [s "abc"] (bench (instance? CharSequence s))) ;; 执行时间平均值:1.358360 ns
(let [x (x.)] (bench (satisfies? p x))) ;; 执行时间平均值:112.649568 ns
(let [y (y.)] (bench (satisfies? p y))) ;; 执行时间平均值:2.605426 µs


*原因*:`satisfies?`调用`find-protocol-impl`来查看一个对象是否实现了协议,这将检查x是否是协议接口的实例或x的类是否是协议实现之一(或者在继承链中会使其成为真)。这个检查相当昂贵且没有缓存。

*提议*:将协议的方法实现缓存扩展到处理(并缓存)实例检查(包括负结果)。

补丁后

(let [x (x.)] (bench (satisfies? p x))) ;; 执行时间平均值:79.321426 ns
(let [y (y.)] (bench (satisfies? p y))) ;; 执行时间平均值:77.410858 ns


*补丁*:CLJ-1814-v7.patch(依赖于CLJ-2426)

25 答案

0

评论者:bronsa

这不太好,我会在今天稍后查看,谢谢

0

评论者:bronsa

这是一个关于如何缓存nil的问题,我决定为nil使用特殊处理,跳过方法缓存,这样就消除了所有关于NIL的奇怪事情,并解决了falsenil之间的不良交互。

0
by

评论者:michaelblume

不确定这是否在本次工单的范围内,但由于这一点未被捕获,应该有更多的协议调度测试。

0
by

评论者:alexmiller

是的,应该肯定添加

0
by

评论者:michaelblume

带有测试的补丁

0
by

评论者:michaelblume

已验证测试在v4补丁中失败

`

 [java] Testing clojure.test-clojure.protocols
 [java]
 [java] FAIL in (test-default-dispatch) (protocols.clj:695)
 [java] expected: (= "Object impl" (test-dispatch false))
 [java]   actual: (not (= "Object impl" "Nil impl"))
 [java]
 [java] FAIL in (test-default-dispatch) (protocols.clj:695)
 [java] expected: (= "Object impl" (test-dispatch true))
 [java]   actual: (not (= "Object impl" "Nil impl"))

`

0
by

评论者:michaelblume

这个补丁错过1.9列车了吗?我们本希望在HoneySQL中做出的一些修复,现在对satisfies表示犹豫,因为它已经很慢了。

0
by

评论者:alexmiller

不一定。我们在1.9之后不会添加新功能,但像这样关于性能的东西仍然是可能的。Rich已经审阅过它,它在我的待筛选清单上。

0
by

评论者:bronsa

已更新补丁以兼容基于实例的协议调度,该工单应先等待CLJ-2426

0
参考: https://clojure.atlassian.net/browse/CLJ-1814(由 bronsa 报告)
...