目前,启用直接链接(DL)的方法主要是非此即彼的,有点像^:redef
的 pinpoint opt-out。根据我的经验,在您仍希望在调试和调查目的中使用此应用程序的情况下,DL 使用起来可能有些笨拙。提前知道哪些函数需要重新编译既繁琐又费神。事实上,我正是因为这个原因而完全不启用 DL。
我想知道如果有一种更灵活的方式来调整 DL,它是否会更加流行。下面是我的想法。
目前,是否使用 DL 的决定是在编译该调用点的 *compiler-options*
时的值。我设想的可替代方案是在函数定义时做出是否使用 DL 的决定,该函数的所有后续调用都遵循这个决定。
让我给你举个例子。Clojure 本身编译了启用 DL 的 clojure.core
命名空间。这意味着 clojure.core
中的函数静态链接到其他 clojure.core
函数。然而,如果开发者禁用了 DL,那么对 clojure.core
函数的调用将经过 Var 解析。我个人不能想象出这种精确行为是有需求的场景。有人想重构他们运行时使用的 clojure.core
函数,同时也愿意让其他代码使用旧版本吗?这是否是语言设计有意鼓励的?
我的第二点是,广泛的 DL 通常只有在用于紧循环中调用的特定函数时才会带来相当实际的性能提升,这些函数得益于 JIT 级联优化,因为它们可以内联。这些性能关键函数可以通过程序分析器可靠地识别,然后只对这些函数启用 DL 就很有意义。目前,唯一确保函数能够 JIT 内联而无需全面采用 DL 的方法就是使用半隐晦的 :inline
函数,这实际上只是一个宏。
在实现方面,可以通过结合一个特殊的*compiler-options* :direct-linking
值(有点类似于*unchecked-math*
可以只是true
或:warn-on-boxed
)和 Var 上的元数据(可以重用当前的 ^:static
)来实现。
简而言之:我想要一种 DL 模式,当某个函数的所有调用点编译时自动进行直接链接,并且还有一种方法可以显式标记一个函数始终使用 DL。其他人觉得这样的特性有用吗?非常愿意听到您的想法。