我来自 Ruby,有点采用单一职责原则、封装、松耦合、可测试的小方法等方法论,所以我的代码往往会频繁地从一个方法跳到另一个方法。这就是我习惯在 Ruby 世界中工作的方式。我认为这是最好的工作方式,主要是用于 BDD,因为一旦你开始拥有执行多项操作的“大型”方法,测试就会变得非常困难。
我想知道这种方法在性能上是否存在明显差异?
我来自 Ruby,有点采用单一职责原则、封装、松耦合、可测试的小方法等方法论,所以我的代码往往会频繁地从一个方法跳到另一个方法。这就是我习惯在 Ruby 世界中工作的方式。我认为这是最好的工作方式,主要是用于 BDD,因为一旦你开始拥有执行多项操作的“大型”方法,测试就会变得非常困难。
我想知道这种方法在性能上是否存在明显差异?
是的,除非你有一个内联的编译器,否则总会有一些性能影响,但是如果你做动态方法查找(如 Ruby 和 Obj-C),你不能内联,所以会有一些影响。但是,它实际上取决于语言和调用约定。如果你在 Objective-C 中有一个调用,你知道开销将是使用 C 调用约定一次(调用objc_msg_send
),然后是方法查找,然后是某种跳转(很可能也是 C 调用约定,但可以是任何东西)。但是,您必须记住,除非您正在编写 C 和汇编,否则几乎看不出有任何区别。
虽然不一定是特定于 Object-C 的,但编译器在非解释或非动态调度语言/运行时中没有内联的太多方法调用会造成性能损失,因为每次调用新函数都需要在堆栈以及设置一个新的堆栈帧,当被调用者返回给调用者时必须清理该堆栈帧。此外,通过引用传递变量的函数可能会导致性能损失,因为函数调用被认为对编译器不透明,从而消除了编译器进行优化的能力......换句话说,编译器无法重新排序读/写操作对作为可修改参数传递给函数的内存地址的函数调用(即指向非const
对象),因为如果对操作进行重新排序,这些内存地址可能会产生副作用。
我认为,尽管最终您只会在紧密的 CPU 绑定循环中真正注意到这些性能损失。例如,任何进行 OS 系统调用的函数调用实际上都可能导致您的程序丢失其在 OS 调度程序中的时间片或被抢占,这将花费比任何函数调用本身更长的时间。
确实存在一些性能影响。然而,大多数系统的性能主要由 I/O 控制,因此方法调度开销只是性能图的一小部分。如果您正在开发一个方法调度开销很大的应用程序,您可能会考虑使用具有更多调度选项的语言进行编码。
Objective-C 中的方法调用相对昂贵(可能至少比 C++ 或 Java 慢 10 倍)。(事实上,由于“鸭子类型”等原因,我不知道是否有任何标准的 Objective-C 方法调用是或可以是内联的。)
但在大多数情况下,Objective-C 的性能主要由 UI 操作(以及 IO 操作和网络操作)支配,普通代码的效率无关紧要。只有当您进行一些密集的计算时,才会关注性能。