8.4.6 总结

深入了解编译器内联机制之后,我们可以写出更加益于编译器优化的代码。例如我们有一个很复杂的函数:

func ReallyBigFunc() {
    // Part 1: Fast Operations with few statements
    // stmt0
    // stmt1
    result := expr()
    if result {
        return
    }

    // Part 2: Slow operations with many statements
    // stmt4
    // stmt5
    // ...
    // stmt100
}

假设该函数使用得极其频繁,而大多数情况下函数都会在第一个 if 语句处返回,只有极少数情况下需要执行后面的 Slow Operation. 由于函数的总体复杂度很大,因此编译器不会对其进行内联,所以程序在执行时需要付出很大的调用开销。一个优化的策略是让编译器将 Part 1 的代码进行内联,我们可以将 Part 2 单独提取为一个函数:

func slowOp() {
    // Part 2: Slow operations with many statements
    // stmt4
    // stmt5
    // ...
    // stmt100
}

func ReallyBigFunc() {
    // Part 1: Fast Operations with few statements
    // stmt0
    // stmt1
    result := expr()
    if !result {
        slowOp()
    }
}

func main() {
    ReallyBigFunc()
}

这样函数 ReallyBigFunc() 的行为不会改变但复杂度降低,对于每个调用函数 ReallyBigFunc() 的地方编译器都可以将其内联。例如上面的 main 函数最终会是如下样子:

func main() {
    // Part 1: Fast Operations with few statements
    // stmt0
    // stmt1
    result := expr()
    if !result {
        slowOp()
    }
}

这样就极大地避免了原函数的调用开销。

最后更新于