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 撰写)
...