【发布时间】:2020-03-19 01:42:30
【问题描述】:
几周前,SBCL 更新了 2.0.2 并带来了 Block 编译功能。我已阅读此article 以了解它是什么。
我有一个问题,(declaim (inline 'some-function)) 和 Block 编译有什么区别?块编译是由编译器自动编译的吗?
谢谢。
【问题讨论】:
标签: compilation lisp common-lisp sbcl
几周前,SBCL 更新了 2.0.2 并带来了 Block 编译功能。我已阅读此article 以了解它是什么。
我有一个问题,(declaim (inline 'some-function)) 和 Block 编译有什么区别?块编译是由编译器自动编译的吗?
谢谢。
【问题讨论】:
标签: compilation lisp common-lisp sbcl
内联编译是一种特殊的优化技术。被调用的函数直接集成到调用函数中——通常使用其源代码——然后编译。
这意味着内联函数可能不仅仅内联在一个函数中,而是内联在多个函数中。
优点:调用函数的开销消失了。
缺点:当内联函数发生更改并且我们希望此更改变得可见时,代码大小会增加并且调用函数需要重新编译。宏有同样的问题。
块编译意味着一堆代码以不同的语义约束一起编译,这使得编译器能够进行一系列新的优化。
Common Lisp 在标准中支持块编译 单个文件。它允许文件编译器假定文件就是这样的代码块。
Common Lisp 标准的示例:
文件中对同一文件中定义的命名函数的调用引用该函数,除非该函数已声明为 notinline。如果函数在运行时单独重新定义或在同一文件中多次定义,后果是不确定的。
这允许代码调用全局函数并且不使用符号的函数单元进行调用。因此,这会为全局函数调用禁用 后期绑定 - 在此文件中和此文件中的函数。
没有说这是如何实现的,但编译器可能只是将代码分配到某个地方,然后调用就跳转到那里。
所以块编译的这部分是在标准中定义的,一些编译器正在这样做。
多个文件的块编译
如果文件编译器可以对一个文件使用块编译,那么多个文件呢?一些编译器也可以告诉文件编译器有几个文件组成了一个块进行编译。 CMUCL 就是这样做的。 SBCL 是从 CMUCL 派生和简化的,直到现在还缺少它。我认为 Lucid Common Lisp(不再积极销售)也确实支持类似的东西。
将它添加到 SBCL 可能也很有用。
【讨论】:
block-compile-files 函数,将一堆文件合并到一个文件中,然后对其进行块编译。你会丢失关于定义来自哪里的信息(或者更确切地说,信息是错误的),但是对于那种我需要所有速度我能得到的情况,这将是一个合理的权衡。