2014-02-26 46 views
3

为了整洁和可重用性,我正在考虑在一个类中放入一堆效用方法。该类不需要任何属性,因此我将这些方法定义为类方法;我认为这是没有真正的需要有这个类的实例浮动...Obj-C:类方法vs实例方法 - 效率差异?

...或者有吗?效率有差异吗? (一个明显的吗?)或者调用类方法的行为与它们是调用类的一部分一样吗?

+0

我的猜测是实例方法比类方法稍快。但这只是一个猜测。但大多数情况下,它们几乎相同 - 都是类似的动态调用。 –

回答

6

丹丹78总体上有正确的答案。自己衡量你的代码总是最好的。事实上,对于这个问题,你可能应该按照你想要的方式来实现它,然后进行度量,并且只在显着减慢你的应用程序时才改变它。

Gavin也是正确的,C函数比类或实例方法更有效。但是,除非你在紧密循环中调用这些方法数百万次,否则方法与C函数的开销可能对你的应用程序无关紧要。

但要回答问题,类方法和实例方法之间基本没有区别。在Objective-C中,类实际上是对象本身,向它们发送消息与向实例对象发送消息相同。每个类基本上都有一个调用类方法的单例对象。

2

与所有关于效率相关困境的案例一样,最好的选择就是从编码的角度来做有意义的事情 - 尽可能让代码尽可能直观和易于阅读。如果事实证明某些事情没有达到预期的速度,那么应该进行相应的分析和优化。

虽然我不希望在这种情况下有任何区别,但可以创建一个方法的类和实例版本,在循环前后运行一百万次,然后比较[NSDate date]调用时代。

2

实际上,最有效的方法是使它们成为C函数。每次调用其中一个时,您都会避免Objective-C运行时的开销。很明显,基于你的问题的措辞,你不需要额外的状态,你保留这些实用方法,因为你正在考虑使他们的类方法无论如何。

当我围绕像这样的实用方法时,我大部分时间都使它们成为C函数,因为它是最干净和最有效的。当我可能用它们来制作一个Objective-C类时,如果它们具有共同的东西,那么将它们按照这种方式组织起来是有意义的,或者如果我需要保持它们的状态。

+0

正确的绝对值。实际上,objc_msgSend的开销很小。 – bbum

+0

@bbum但效用函数可以很容易地用于紧密循环,在这种情况下,开销可能会产生可测量的差异。此外,如果它们只是不需要或不一定属于Objective-C类的实用程序函数,那么没有理由不走这条路线。如果您需要保留一些状态或其他数据,则类路由主要是有意义的。 – Gavin

+0

是的 - 同意了。如果是这种情况,那么充分利用“静态内联”可能是正确的选择。我更加指出,方法调用与C函数的开销并不重要。如果足以产生影响,则更有可能出现算法问题。 – bbum

1

I made a sample project比较调用实例方法类方法或C函数。下面是一些例子输出:

Class methods: Time to complete: 0.00415796 
Single instance: Time to complete: 0.00437099 
Using Singleton: Time to complete: 0.071667 
Using Global:  Time to complete: 0.00534797 
Using C function: Time to complete: 0.00302202 

,你应该从该得到的主要结论是:差异可以忽略不计;使用仪器来分析实际性能瓶颈。

为了回到原来的问题,您应该使用类方法,因为您的方法不依赖于实例可能容纳的任何状态(属性)。性能明智,这只能帮助,因为使用实际的实例意味着你必须以某种方式分配和访问该实例,这增加了开销(再次,所有这些都可以忽略不计)。使用C函数将会不明显更快,但是您将无法像继承类方法那样继承和重写该C函数。

+1

单身人士的结果令人惊讶。我原以为它会更像单实例的结果。 – Oliver

+0

取决于实施。 – bbum

+0

单例结果在每次调用方法之前首先调用一个方法来获取单例,另外它可能会使编译器更难以优化代码,并且可能使其更不易于缓存。如果我们只是检索单例并将其保存在局部变量中,它几乎等于单实例结果。至于子类化,人们通常不会对实用函数进行子类化,所以Objective-C类别不太可能需要它。性能关键代码会有所不同。 – Gavin