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

欢迎!请查阅关于页面了解此功能的一些信息。

0
Clojure
以下是Michał Marczyk在下面的讨论线程中发现的一个性能较差的示例的描述。

以下是以下两个编译版本的差异:


(defn foo [x]
  (if (> x 0)
    (inc x)
    (locking o
      (dec x))))





(defn bar [x]
  (if (> x 0)
    (inc x)
    (let [res (locking o
                                              ">
      res)))


相当显著。foo被编译为一个单独的类,通过一个单独的调用方法来处理调用;bar被编译为bar的类和一个额外的类来处理locking o (dec x)部分 -- 可能与手动编写的锁定部分的输出非常相似(尽管我还没有真正看过那个)。内部函数是一个闭包,调用它涉及到分配一个闭包对象;它的构造函数接收封闭的局部变量作为参数并将它们存储在两个字段(lockee和x)中。然后它们被加载到闭包的调用方法体中等。


注意:摘要行可能过于狭隘地描述了根本原因,这仅仅是一个问题被注意到并检查的第一个案例。如果诊断了此问题,请更正摘要和此描述。

在此处查看Clojure组上的讨论线程:https://groups.google.com/forum/#!topic/clojure/x86VygZYf4Y

2 答案

0
_评论由:hiredman_发出_

也许它对其他人来说已经很清楚,但对我不太清楚。

原因


(defn bar [x]
  (if (> x 0)
    (inc x)
    (let [res (locking o
                                              ">
      res)))


生成第二个类的原因是锁定是一个宏,它在其展开中包含了一个try/finally形式。

将try/finally形式的返回结果绑定到一个结果(如在let中)将需要一些非常复杂的代码生成,而不需要添加额外的函数,因此当然,Clojure编译器会添加这个额外的函数。
0
参考: https://clojure.atlassian.net/browse/CLJ-1296 (由jafingerhut报告)
...