Common lisp 如何在公共Lisp中内联函数
有人能告诉我如何在CommonLisp中内联函数吗? 我有很多小函数,它们总是被调用,所以节省这些函数调用的成本是很好的 例如,如何在“调用者”函数中内联“独立”函数Common lisp 如何在公共Lisp中内联函数,common-lisp,inline,Common Lisp,Inline,有人能告诉我如何在CommonLisp中内联函数吗? 我有很多小函数,它们总是被调用,所以节省这些函数调用的成本是很好的 例如,如何在“调用者”函数中内联“独立”函数 (defun standalone () (* 2 5)) (defun caller () (standalone)) 文件是 (但请记住,定义一个总是返回数字文本10的函数没有多大意义…请参阅食谱: 如果编译器支持,内联声明将用函数体替换函数调用。它将节省函数调用的成本,但可能会增加代码大小。使用内联函数的最佳情况可能
(defun standalone ()
(* 2 5))
(defun caller ()
(standalone))
文件是
(但请记住,定义一个总是返回数字文本10的函数没有多大意义…请参阅食谱:
如果编译器支持,内联声明将用函数体替换函数调用。它将节省函数调用的成本,但可能会增加代码大小。使用内联函数的最佳情况可能是那些小但常用的函数。下面的代码片段展示了如何鼓励和禁止内联代码
;; The globally defined function DISPATCH should be open-coded,
;; if the implementation supports inlining, unless a NOTINLINE
;; declaration overrides this effect.
(declaim (inline dispatch))
(defun dispatch (x) (funcall (get (car x) 'dispatch) x))
;; Here is an example where inlining would be encouraged.
;; Because function DISPATCH was defined as INLINE, the code
;; inlining will be encouraged by default.
(defun use-dispatch-inline-by-default ()
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here only affects this function.
(defun use-dispatch-with-declare-notinline ()
(declare (notinline dispatch))
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here affects all following code.
(declaim (notinline dispatch))
(defun use-dispatch-with-declaim-noinline ()
(dispatch (read-command)))
;; Inlining would be encouraged becuase you specified it.
;; The INLINE here only affects this function.
(defun use-dispatch-with-inline ()
(declare (inline dispatch))
(dispatch (read-command)))
一些实现,如Allegro CL编译器
由
define compiler macro
(不同于defmacro
)创建的宏也可以用于内联代码。非常感谢,它很有效。实际上,“独立”函数没有任何意义,但我想知道函数调用的成本,我发现“独立”需要0.42秒,而“调用方”需要0.61秒(执行100000000次)。因此,添加的函数调用似乎消耗了“独立”函数总成本的50%。我不知道与其他语言相比,这种成本有多高,但我还是觉得它非常昂贵,值得担心。正如Ehvince在他的回答中指出的,内联与否是代码大小和执行时间之间的权衡。所有语言的调用机制都是类似的:在堆栈上推送返回地址、所有要更改的寄存器的值以及参数值,进行调用,将参数从堆栈中弹出;然后,在子例程调用结束时,恢复寄存器和返回地址,恢复堆栈并从那里恢复执行。有许多可能的复杂性(例如返回值的处理方式),但是,是的,函数调用是昂贵的。不可读的代码更是如此……感谢您提供了这个很棒的资源:)很有趣。不熟悉Allegro CL.“用户定义的函数从不内联编译。”这对于商业产品来说很奇怪。不相信他们的理由。你需要的是一个变量,而不是一个函数!
;; The globally defined function DISPATCH should be open-coded,
;; if the implementation supports inlining, unless a NOTINLINE
;; declaration overrides this effect.
(declaim (inline dispatch))
(defun dispatch (x) (funcall (get (car x) 'dispatch) x))
;; Here is an example where inlining would be encouraged.
;; Because function DISPATCH was defined as INLINE, the code
;; inlining will be encouraged by default.
(defun use-dispatch-inline-by-default ()
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here only affects this function.
(defun use-dispatch-with-declare-notinline ()
(declare (notinline dispatch))
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here affects all following code.
(declaim (notinline dispatch))
(defun use-dispatch-with-declaim-noinline ()
(dispatch (read-command)))
;; Inlining would be encouraged becuase you specified it.
;; The INLINE here only affects this function.
(defun use-dispatch-with-inline ()
(declare (inline dispatch))
(dispatch (read-command)))