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》相关的有趣操作,并修复了《false》和《nil》之间的不和谐交互。

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

不一定。我们不添加新特性,但像这种性能问题仍然可行。Rich已经审查过它。它在我的筛选清单里。

0

评论由:bronsa

更新了补丁以在新的基于实例的协议调度后工作,这个工单应先等待 CLJ-2426

0
by
参考:https://clojure.atlassian.net/browse/CLJ-1814(由 bronsa 提出)
...