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纳秒
(let [x (x.)] (bench (satisfies? p x))) ;; 执行时间平均值:112.649568纳秒
(let [y (y.)] (bench (satisfies? p y))) ;; 执行时间平均值:2.605426微秒


*原因:* `satisfies?`调用`find-protocol-impl`以检查一个对象是否实现协议,这会检查x是否是协议接口的一个实例或者x的类是否是协议的实现之一(或者如果它在会导致这种情况的继承链中)。这个检查相当昂贵,并且没有被缓存。

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

补丁后

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


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

25 答案

0

评论由:bronsa

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

0

评论由:bronsa

这是关于如何缓存nil的一个问题,我决定将nil特别处理以跳过方法缓存,删除所有关于NIL的奇怪操作,并修复falsenil之间的不良交互。

0

评论者:michaelblume

不确定这一点是否在本次工单的范围内,但由于这一项没有被发现,可能应该有更多的协议调度测试。

0

评论者:alexmiller

是的,一定要加

0

评论者:michaelblume

带有测试补丁

0

评论者: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

评论者:michaelblume

这个补丁错过了1.9列车吗?我们希望在HoneySQL中修复的一些问题,现在对于satisfies(它的速度太慢)我犹豫是否设置。

0

评论者:alexmiller

不一定。我们不会在1.9之后添加新功能,但像这样的性能问题仍然可能。它已经由Rich审核过。它在我要审查的项目列表中。

0

评论由:bronsa

更新补丁以适应新的基于实例的协议调度,此工单应先等待CLJ-2426。

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