内联比递归定义如何有效?

Cpp*_*ner 0 language-agnostic paradigms scheme inline

我的《编程范例》教科书,《编程语言基础》(第3版)第1章有一个练习:

练习1.12

通过用subst-in-s-exp的定义代替它的定义并简化生成的过程,消除对subst-in-s-exp的一次调用。结果将是不需要subst-in-s-exp的subst版本。这项技术称为内联,用于优化编译器。

原始代码将具有两个功能:subst并且subst-in-sexp基本上将输入符号中所有出现的旧符号替换为新符号。

(define subst
  (lambda (new old slist)
    (if (null? slist) '()
        (cons
         (subst-in-s-exp new old (car slist))
         (subst new old (cdr slist))))))

(define subst-in-s-exp
  (lambda (new old sexp)
    (if (symbol? sexp)
        (if (eqv? sexp old) new sexp)
        (subst new old sexp))))
Run Code Online (Sandbox Code Playgroud)

这个问题的答案是消除subst-in-sexp,这就是

(define subst
  (lambda (slist old new)
    (cond
      [ (null? slist) '()]
      [ (eqv? (car slist) old) (cons new (subst (cdr slist) old new))]
      [ else (cons (car slist) (subst (cdr slist) old new))])))
Run Code Online (Sandbox Code Playgroud)

为什么除了更短(更少的空间)外,内联更好?递归的大小是否改变?换句话说,这种内联会创建更少的堆栈元素吗?

此外,如何使用这个想法来使我的C ++,Python和Java代码更快?我可以轻松扩展这个想法吗?谢谢。

我在Scheme(实际上是Racket)中对此进行了标记,因为这是本书中使用的语言。

小智 5

内联是相当标准的编译器优化,但是正如AoeAoe所说,通常最好编写代码以使其可读并让编译器为您完成所有内联。

内联的直接好处是它消除了代码中的分支。这意味着您的CPU可以继续直接阅读代码,而不必花费几个时钟周期来查找要执行的下一部分代码。

但是,内联还有其他好处。您最终将获得更大的代码块,这意味着编译器需要处理更多的代码和数据。它可能能够将更多内容粘贴到寄存器中,或者进行连续折叠以消除更多计算。编译器还可以更好地执行指令调度,因为它有更多的指令可以移动。

缺点是内联会增加您生成的代码大小。尤其是在现代CPU运行速度比内存快得多的情况下,内联较少的代码通常会更好,以便将所有热部分代码保留在L1缓存中。