Objective c 向类中添加类别是否会影响性能

Objective c 向类中添加类别是否会影响性能,objective-c,cocoa,performance,Objective C,Cocoa,Performance,我刚接触Cocoa,在开始使用分类之前有一个小问题 假设您向NSString添加了一个新方法。这是否会影响正常NSString消息的性能,或者只有在方法调用与标准方法集不匹配时才检查类别方法?如果您是Cocoa新手,您不应该担心这一点。除了在没有分析的情况下不对性能进行假设这一基本规则之外 如果需要提供功能,可以在可以的地方添加。如果扩展一个类是有意义的,那么就这样做。如果不将该功能添加到NSString,则必须在其他地方提供该功能。如果您在另一个类中执行此操作,则会增加不同级别的复杂性 就个人

我刚接触Cocoa,在开始使用分类之前有一个小问题


假设您向NSString添加了一个新方法。这是否会影响正常NSString消息的性能,或者只有在方法调用与标准方法集不匹配时才检查类别方法?

如果您是Cocoa新手,您不应该担心这一点。除了在没有分析的情况下不对性能进行假设这一基本规则之外

如果需要提供功能,可以在可以的地方添加。如果扩展一个类是有意义的,那么就这样做。如果不将该功能添加到NSString,则必须在其他地方提供该功能。如果您在另一个类中执行此操作,则会增加不同级别的复杂性

就个人而言,我会担心你的应用程序的设计。如果有意义,请使用一个类别,如果您真的关心性能,请在应用程序运行后对其进行评测


尽管我在这里做了一个假设,但我想说,与调用NSString的速度相比,应用程序的性能更可能受到更大的影响。除非,您正在进行大量的NSString调用,在这种情况下,我们将再次进行分析。

所有方法都使用动态分派发送到消息,到类别的方法不会干扰“正常”消息

从性能方面看,运行时处理将方法与所讨论的类相关联的问题,因此这需要一次性的成本,但每个对象都没有变化。我不关心类别的性能,而是要小心确保通过类别添加的方法不包括默认方法或其他类别中指定的方法。问题通常就是从这里开始的。

一般来说,不是

objc_msgSend()
保留一个伪最近最少使用的缓存,该缓存包含每个类上的最近
SEL
IMP
查找。与往常一样,细节是“实现私有细节”,但可以合理地说,不管选择器的数量如何,查找时间平均为~
O(1)
。最常见的方法是使用一个小的哈希表——如果选择器在缓存中,那么分派基本上是即时的。如果选择器不在缓存中,则需要执行“慢路径”查找

然而,即使是“慢路”也可能相当快。有很多数据结构可以使用,例如红黑树,它们提供了出色的次指数查找时间,无论选择器的数量如何,都可以很好地扩展—通常在
O(log2(selectorCount))
范围内。同样地,
libobjc
如何处理这些细节是私有的,但是有如此多的数据结构,无论要搜索的项目数量多少,都可以轻松扩展,因此没有理由让这种事情出现在你的雷达上

< >通过<代码> NM< /代码>快速检查,在AppKit建立了7771个选择器,在27510个选择器中,总共有35281个选择器。加入QuickTime、CoreData、WebKit、Quartz,您就可以轻松地使用多达50K的选择器。在
log2
查找时间增长率下,选择器数量增加一倍将使最坏情况下的时间增加不到10%

总之:
objc\u msgSend()
使用一个小的基于哈希的缓存为最近使用的选择器提供
O(1)
查找时间。。。而且存在高度的时间局部性,因此无论系统中存在多少选择器,绝大多数调度都是在
O(1)
时间内完成的。缓存的自然效果是根据您的特定使用模式“调优”自身。即使在缓存未命中的情况下,最坏情况下的查找时间也可能是~
O(log2(selectorCount))
bound,这很好,而且在实践中可能比这更好

值得一提的是,我花了很多时间调整代码以提高速度。即使是在多线程的情况下,我将所有CPU都绑定到Objective-C中进行大量分析->NSView/OpenGL重结果渲染,我也只能看到
objc\u msgSend()
在分析
Shark.app
时占用1-4%的CPU。。。这是最糟糕的情况,执行大量Objective-C消息调度。这对我来说从来都不是一个问题,无论速度有多小的损失,它都可以轻松地用100倍的编程效率来弥补

另见:





编辑:这有多奇怪:。不能说我知道整个Obj-C消息发送系统都获得了专利。。。。我想你真的可以得到任何东西的专利。我要给字母表申请专利,然后大收费,宝贝

这些对nsstring类别有意义吗?”(NSString*)firstStringBetween:start和:end''(NSArray*)stringsbween:start和:end'即[string stringbetween:@”(“and@”)“]这些名称看起来不错,尽管它们没有尽可能详细,我希望文档能够弥补这一点。但只要你知道他们的意思。。。一般来说,我会检查现有Cocoa方法的名称并使用它们所使用的模式。避免方法名称冲突的最简单方法是为该类别的所有方法添加前缀。XYZfirstStringBevering:…没错,但它违反了方法名的良好设计。我认为了解冲突的可能性有助于避免此类问题。为广泛使用的类添加类别的程序员应该特别警惕潜在的陷阱。也就是说,任何有效的东西都比不起作用的东西好。:-)命名良好的分类方法的问题在于,它们最有可能与苹果的方法发生冲突。我刚刚在NSMutableArray中添加了-pop,UINaviagtionController就爆炸了。教训:去吧