Go,封装和性能

Go, encapsulation and perfomance

我正在探索的代码:

type Stack struct {
    length int
    values []int
}

func (s *Stack) Push(value int) {
    // ...
}

func (s *Stack) Pop() int {
    // ...
}

func (s *Stack) Length() int {
    return s.length
}

方法 PushPop 更改 Stack 结构中的 length 字段。而且我想从其他文件中隐藏此字段以防止像 stack.length = ...(手动 length 更改)这样的代码。但是我需要有能力阅读这个字段,所以我添加了 getter 方法 - Length.

我的问题是:

不应该 stack.Length() 变得比 stack.length 慢,因为它是一个函数调用吗?我学过一点汇编程序,我知道程序调用一个函数应该执行多少操作。我是否理解正确:通过添加 getter 方法 stack.Length() 我保护了那些使用我的库的人免受不良使用,但它的成本 - 程序的性能?这其实不只是围棋

Shouldn't stack.Length() become slower than stack.length, because it is a function call?

Objection! Assumes facts not in evidence.

具体来说:

  1. 为什么你认为它是一个函数调用?看起来像一个,但实际的Go编译器通常会扩展代码线.
  2. 为什么您认为函数调用比内联代码慢?在实际计算机上测量实际程序时,有时函数调用更快 比内联代码。事实证明,关键部分通常是正在执行的指令及其操作数是否已经在适当的 CPU 缓存中。有时,内联扩展函数会使程序 运行 变慢。

编译器应该进行内联扩展,除非它使程序 运行 变慢。编译器在预先或 post 方面有多好 - 检测这种减速(如果存在)是一个单独的问题。在这种特殊情况下,给定函数定义,编译器几乎肯定会直接扩展函数,因为访问 stack.length 可能是一条指令,调用函数将是一条指令,在这里决定权衡会很容易。