如果我使用Objective-C编写低级代码,我的iPhone应用程序是否会受到性能影响?
在iPhone或其他便携式硬件上对CPU密集型或GPU密集型应用程序进行编程时,必须做出明智的algorithm决策,才能使代码更快速。
但是,如果您使用的语言比另一种语言执行得更差,即使是很好的algorithmselect也会变慢。
是否有任何比较Objective-C到C ++的硬数据,特别是在iPhone上,但可能只是在Mac桌面上,以performance各种类似的语言方面? 我对这篇比较C和Objective-C的文章非常熟悉,但这是将两种面向对象的语言相互比较的一个更大的问题。
例如,C ++的vtable查询是否比Obj-C消息更快? 快多less? 线程,多态性,sorting等。在我去寻求build立一个具有重复对象模型和各种testing代码的项目之前,我想知道是否有人已经做了这个以及结果在哪里。 这种types的testing和比较本身就是一个项目,可能需要相当长的时间。 也许这不是一个项目,但只有两个产出可以比较。
我正在寻找硬数据 ,而不是传福音。 就像你们中的许多人一样,我因各种原因而爱和恨两种语言。 而且,如果有人在那里积极追求同样的事情,我会很有意思地在代码中看到最终的结果,而且我相信其他人也会有帮助。 我的猜测是,他们都有优势和弱点,我的目标是要找出他们是什么,以便他们可以避免/利用在现实世界的情况下。
Mike Ash在他的“通用操作性能比较”一文中,针对各种Objective-C方法调用与C和C ++的性能进行了比较 。 另外,Savoy Software的这篇文章对于使用Objective-C ++来调整iPhone应用程序的性能是一个很有趣的解读。
我倾向于比Objective-C ++更清楚Objective-C的清晰的描述性语法,而且还没有发现语言本身成为我的性能瓶颈的来源。 我甚至倾向于做一些我知道牺牲一点性能的东西,如果他们让我的代码更加可维护的话。
是的,写得很好的C ++速度要快得多。 如果你正在编写性能关键的程序,而你的C ++速度不及C(或者在几个百分点之内),那就错了。 如果你的ObjC实现和C一样快,那么通常是错误的 – 也就是说这个程序可能是ObjC OOD的一个坏例子,因为它可能使用了一些“脏”的技巧来在它所操作的抽象层之下,例如直接ivar访问。
Mike Ash的“比较”很具误导性 – 我绝不会推荐比较你编写的程序执行时间的方法,或者推荐它比较C vs C ++与ObjC。 所呈现的结果是从禁用编译器优化的testing中提供的。 当您测量执行时间时,禁用优化编译的程序很less相关。 将其视为比较C ++与Objective-C的基准是有缺陷的。 该testing还比较了单个function,而不是整个现实世界的优化实现 – 单个function与两种语言以完全不同的方式组合在一起。 对于优化实现来说,这远远不是一个现实的性能基准。 示例: 启用优化后, IMP
caching与虚拟函数调用一样慢。 静态调度(相对于dynamic调度,例如使用virtual
调用)以及调用已知的C ++types(dynamic调度可能被绕过)可能会被积极优化。 这个过程被称为虚拟化,当它被使用时,被声明为virtual
的成员函数甚至可以是inline
。 在Mike Ashtesting中,有很多调用已经被声明为virtual
并且有空的成员函数的调用:当types是已知的时候,这些调用被完全优化,因为编译器看到实现并且能够确定dynamic调度是不必要的。 编译器也可以在优化版本中消除对malloc
调用(有利于堆栈存储)。 因此,在C,C ++或Objective-C中启用编译器优化可以在执行时间上产生巨大的差异。
这并不是说所呈现的结果完全没有用处。 如果您想确定在一个平台或体系结构与另一个平台或体系结构上的pthread_create
或+[NSObject alloc]
花费的时间之间是否存在可测量的差异,则可以获得有关外部API的一些有用信息。 当然,这两个例子将在你的testing中使用优化的实现(除非你正在开发它们)。 但是,为了在编译的程序中比较一种语言…所提供的结果在禁用优化时是无用的。
对象创build
还要考虑ObjC中的对象创build – 每个对象都是dynamic分配的(例如在堆上)。 使用C ++,可以在堆栈上创build对象(例如,大约与创buildC结构并在许多情况下调用简单函数一样快),在堆上或作为抽象数据types的元素。 每次你分配和释放(例如,通过malloc / free),你可能会引入一个锁。 当您在堆栈上创build一个C结构或C ++对象时,不需要locking(虽然内部成员可能使用堆分配),而且通常只需要几条指令或几条指令以及一个函数调用。
而且,ObjC对象是引用计数实例。 在性能危急的C ++中,实际需要一个对象成为std::shared_ptr
是非常罕见的。 在C ++中使每个实例成为一个共享的引用计数实例是没有必要的。 用C ++来控制所有权和使用寿命的可能性更大。
数组和集合
C和C ++中的数组和集合也使用强types容器和连续内存。 由于下一个元素的成员的地址通常是已知的,所以优化器可以做的更多,而且你有很好的caching和内存局部性。 使用ObjC,对于标准对象(例如NSObject
)来说,这远非现实。
调度
关于方法,许多C ++实现使用很less的虚拟/dynamic调用,特别是在高度优化的程序中。 这些是优化器的静态方法调用和饲料。
使用ObjC方法,每个方法调用(objc消息发送)都是dynamic的,因此是优化器的防火墙。 最终,这会导致许多限制或不便之处,因为在编写性能至关重要的ObjC时,如何将性能降至最低。 这可能导致更大的方法,IMPcaching,频繁使用C.
一些实时应用程序不能在其渲染path中使用任何 ObjC消息。 无 – audio渲染就是一个很好的例子。 ObjC调度根本不是为实时目的devise的; 分配和locking可能在消息对象后面发生,使得objc消息的复杂度/时间不可预知,以致audio呈现可能错过其最后期限。
其他特性
C ++还为其许多库提供了generics/模板实现。 这些优化非常好。 它们是types安全的,并且可以使用模板进行大量的内联和优化(考虑它在编译时发生的多态性,优化和专业化)。 C ++增加了几个在严格的ObjC中不可用或不可比较的特性。 试图直接比较不同的语言,对象和库是不是很有用 – 这是实际实现的一个非常小的子集。 考虑到devise和实现的许多方面,最好将问题扩展到图书馆/框架或真正的计划。
其他点
C和C ++符号可以在构build的不同阶段(剥离,死代码清除,内联和早期内联以及链接时间优化)更容易地移除和优化。 这样做的好处包括减less二进制大小,减less启动/加载时间,减less内存消耗等。对于单个应用程序来说,这可能不是什么大不了的事情; 但如果你重复使用了大量的代码,那么你应该这样做,那么你的共享库可能会给程序增加许多不必要的权重,如果实现了ObjC的话 – 除非你准备跳过一些火红的箍筋。 因此,可扩展性和重用性也是大中型项目和重用性较高的群体的一个因素。
包括图书馆
ObjC库实现者也为环境进行优化,所以它的库实现者可以利用一些语言和环境特性来提供优化的实现。 虽然在纯ObjC中编写优化程序时有一些非常重要的限制,但Cocoa中存在一些高度优化的实现。 这是Cocoa的强项之一,尽pipeC ++标准库(有些人称之为STL)也是不容易的。 cocoa比C ++运行在更高的抽象层次 – 如果你不清楚自己在做什么(或者应该做什么), 靠近金属的操作确实会让你付出代价 。 如果你不是某个领域的专家,那么回到一个好的图书馆实施是一件好事,除非你真的准备好学习。 同样,cocoa的环境也是有限的。 您可以find更好地使用操作系统的实现/优化。
如果你正在编写优化的程序,并且在C ++和ObjC中都有这样的经验,那么干净的 C ++实现通常比干净的 ObjC快两倍(是的,你可以和Cocoa比较)。 如果你知道如何优化,你通常可以比更高层次的通用抽象更好。 虽然,一些优化的C ++实现将比Cocoa快或慢(例如,我最初的文件I / O尝试比Cocoa慢 – 主要是因为C ++实现初始化它的内存)。
这很大程度上取决于您熟悉的语言function。 我使用两种语言,他们都有不同的优势和模式/模式。 它们相得益彰,两者都有很好的图书馆。 如果你正在实现一个复杂的,性能关键的程序,正确使用C ++的特性和库会给你更多的控制权,并为优化提供显着的优势,这样在正确的手中,“好几倍”是一个很好的默认预期不要指望每次都赢,或者没有一些工作,但是)。 记住,理解C ++需要几年时间才能真正达到这一点。
我将大多数性能关键path保留为C ++,但也意识到ObjC对于某些问题也是一个非常好的解决scheme,并且有一些非常好的库可用。
收集“硬数据”非常困难,因为这并不是误导。
像你这样做function到function比较的最大问题是这两种语言鼓励非常不同的编码风格。 Objective-C是一种dynamic语言,使用鸭子打字,典型的C ++用法是静态的。 同样的面向对象的体系结构问题可能会有非常不同的使用C ++或Objective-C的理想解决scheme。
我的感觉(因为我在这两种语言中编写了很多,主要是在大型项目上):为了最大限度地提高Objective-C的性能,必须写得与C非常接近。而使用C ++,可以更多地使用语言与C相比的任何性能损失
哪一个更好? 我不知道。 对于纯粹的性能,C ++将永远有优势。 但Objective-C的OOP风格肯定有其优点。 我绝对认为保持一个理智的build筑与它更容易。
这实际上不是一般可以回答的问题,因为这取决于您如何使用语言function。 两种语言都会有快速的东西,慢的东西,有时快,有时慢的东西。 这真的取决于你使用什么以及如何使用它。 唯一的方法是确定你的代码。
在Objective C中,你也可以编写c ++代码,所以在Objective C中编码可能更容易,如果你发现某些东西不能很好地运行,那么你可以写一个c ++版本看看是否有帮助(C ++往往在编译时更好地优化)。 如果你正在接口的API被写入,Objective C将会更容易使用,另外你可能会发现它的OOP风格更容易或更灵活。
最后,你应该用你知道的,你可以写出安全,健壮的代码,如果你发现需要特别注意其他语言的区域,那么你可以交换。 X代码允许你在同一个项目中编译。
差不多两年前,我在iPhone 3G上做了一些testing,那些日子里没有任何文档或硬编码。 不知道他们仍然是多么有效,但源代码张贴和附加。
这不是一个非常广泛的testing,我主要感兴趣的NSArray与C数组迭代大量的对象。
http://memo.tv/nsarray_vs_c_array_performance_comparison
http://memo.tv/nsarray_vs_c_array_performance_comparison_part_ii_makeobjectsperformselector
您可以看到C数组在高迭代时速度更快。 从那以后,我意识到瓶颈可能不是NSArray的迭代,而是发送消息。 我想尝试methodForSelector并直接调用方法来看看有多大的差异,但从来没有得到它。 根据Mike Ash的基准testing,它的速度只有5倍多。
我没有Objective C的硬数据,但是我确实有一个很好的地方去寻找C ++。
根据Bjarne Stroustroup在C ++( http://www.2.research.att.com/~bs/hopl2.pdf )早期的反思,C ++从C开始,所以C ++可以被认为是(像Objective C )将C推到了面向对象的极限。
这些限制是什么? 在1994 – 1997年的时间框架内,许多研究人员发现,由于dynamic绑定的缘故,面向对象的代价是有成本的,例如当C ++函数被标记为虚拟的时候,有可能没有儿童类来覆盖这些函数。 (在Java和C#中,所有的函数都希望ctors本质上是虚拟的,而且你不能做太多的工作。)IBM Research Tokyo的研究人员在“Java实时编译器的虚拟化技术研究”他们用来对付这个问题的技术,包括来自UrzHölzle和Gerald Aigner的技术。 UrzHölzle在与Karel Driesen分开的论文中表示,C ++程序平均有5.7%的时间花费在调用虚拟函数(例如vtables + thunk)上。 后来他和一些Smalltalk研究人员合作,结束了Java HotSpot虚拟机解决OO中的这些问题。 这些function中的一部分被回溯到C ++(例如“保护”和exception处理)。
正如我所提到的,C ++是静态types的,其中Objective C是鸭子types的。 执行中的性能差异(但不是代码行)可能是这种差异的结果。
这项研究说,要真正在CPU密集型游戏中获得性能,你必须使用C.链接的文章是完整的,你可以运行一个XCode项目。
我相信底线是:使用Objective-C,你必须与iPhone的function交互(毕竟, 把蹦床放在任何地方都不会对任何人有好处 ),但是当涉及到循环时,像vector对象类或密集型数组访问,坚持使用C ++ STL或C数组来获得良好的性能。
我的意思是看到position = [[Vector3 alloc] init] ;
将是非常愚蠢的position = [[Vector3 alloc] init] ;
。 如果您使用像位置vector这样的基本对象的引用计数,则只需要提高性能。
是。 c ++在性能/performance力/资源权衡方面至高无上。
“我正在寻找硬数据,而不是传福音”。 谷歌是你最好的朋友。
-
obj-c nsstring是由苹果工程师交换与c + +的性能。 在资源受限的设备中,只有c ++将其作为MAINSTREAM的oop语言来裁减。 NSString stringWithFormat很慢
-
对象抽象被解构为基于过程的性能结构,否则MAGNITUDE的顺序比java慢! 作者也意识到消息caching – 但没有去。 所以用c ++来完成大量的小型玩家/敌人对象的build模,或者使用obj-c来创build一个简单的OOP封装的程序结构。 可以有一个等同于程序+面向对象编程= obj-c的范例。 http://ejourneyman.wordpress.com/2008/04/23/writing-a-ray-tracer-for-cocoa-objective-c/