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

欢迎!请查看关于页面以了解更多此机制的信息。

+2
编译器
编辑

盲目启用直接链接可能会破坏库,我无法控制这些库中受影响的变量,但我仍希望至少在我自己的代码的部分提高性能。

以下方案可行吗?

(binding [clojure.core/*compiler-options* 
  {:direct-linking true}]
  ,,,
  )

以下是文档:https://docs.clojure.org/clojure.core/*compiler-options*

1 回答

0

会破坏库

怎么破坏?

重要的是,当编译发生时,编译器绑定设置为何值。编译发生在加载时,因此应该可以对此进行巧妙处理,但这将是巧妙的。我认为有另一个问题涉及在直接链接中提供更多控制权的问题。

"怎么会这样?"

在我看来,反编译代码+根据Clojure文档中'直接链接'编译器键可以在可能的情况下启用直接函数调用,而不是通过var进行间接调用。

假设我的Clojure代码使用了某些第三方Clojure库。
使用'lein uberjar',我可以在生成的结果jar文件中看到第三方Clojure库的编译后的类文件。

如果我用带有'-Dclojure.compiler.direct-linking=true'的'lein uberjar'运行,那么有没有可能破坏依赖于一些_runtime_重新绑定全局变量的魔法性的第三方库,这可能会因直接链接而消失?
动态变量不会进行直接链接。
明白了

至于重复的def和alter-var-root呢?

据我所知,在启用直接链接时,alter-var-root会更改var,但其引用已被编译,所以调用点不会受到影响,将继续使用编译后的直接函数调用

对吗?
by
— 可能会破坏库
— 如何做到这一点?

是的,我很困惑并且做错了。我的意思是,当整个代码库启用直接链接时,与库交互时可能会出现问题。

第一个场景可能不太可能发生,但库可能期望用户以不同的方式实现协议并重新定义实例,或者出于某些原因我们希望这样做。

    ;; 库
    
    (defprotocol MyProtocol
      (my-function [this]))
    
    (def my-instance (reify MyProtocol
                                            (my-function [this] (println "hello"))))
    
    
    ;; 应用程序
    
    ;; 我们不能重新定义 my-instance
    ;; 我们也不能将其设置为 ^:redef,因为它在库中

第二种情况是当我们在处理库时忘记将变量标记为 ^:redef,应用程序将看不到其中的更改。

    ;; 库
    (def my-var 10)
    ;; 我们试图在编译完所有东西后更新这个变量
    
    ;; 应用程序
    (defn use-var []
      (println my-var))

这两个例子可能都是人为构建的,我没有一个具体的问题要问,形式是“如何做到以下操作?”,但是直接链接只是简要地记录下来,没有解释如何以细粒度方式处理它,这就是为什么我提问。

Andray Shotkin 检查了一下,显然这可以工作,代码确实是直接链接而没有变量。

    (binding [*compiler-options* {:direct-linking false}]
      (clj-java-decompiler.core/decompile (fn []
                                            (seq (map :x [1 2 3])))))
    
    (binding [*compiler-options* {:direct-linking true}]
      (clj-java-decompiler.core/decompile (fn []
                                            (seq (map :x [1 2 3])))))
                                          
因此,我在这里粘贴了一个如何为一个命名空间启用直接链接的示例,以防万一。以防我完全忘记这次对话,将来再次查找直接链接哈哈。

    (ns my-namespace
     (:require [clojure.core :as core]))
    
     (:require [clojure.core :as core]))
     Binding [core/*compiler-optionsromium /*compiler-options*] {:direct-linking true}]
     ,,,
     )
...