代码之家  ›  专栏  ›  技术社区  ›  slf

如果我将Objective-C用于低级代码,我的iPhone应用程序是否会受到性能冲击?

  •  68
  • slf  · 技术社区  · 16 年前

    在iPhone或其他便携式硬件上对CPU密集型或GPU密集型应用程序进行编程时,您必须做出明智的算法决策,以使代码快速运行。

    但是,如果您使用的语言的性能比其他语言差,那么即使是很好的算法选择也会很慢。

    有没有比较Objto-C到C++的硬数据,特别是在iPhone上,但可能只是在Mac桌面上,用于各种类似语言方面的性能?我很熟悉 this article comparing C and Objective-C 但这是一个比较两种面向对象语言的更大问题。

    例如,C++ VSt查找是否真的比Obj-C消息快?多快?线程、多态性、排序等。在我用重复的对象模型和各种测试代码构建项目之前,我想知道是否有人已经这样做了,结果在哪里。这种类型的测试和比较本身就是一个项目,可能需要相当长的时间。也许这不是一个项目,但只有两个输出可以比较。

    我在寻找 硬数据 不是福音。像你们中的许多人一样,我爱和恨这两种语言有很多原因。此外,如果有人在那里积极地追求同样的事情,我会有兴趣在一些代码中投出一些代码来查看最终的结果,我相信其他人也会帮上忙。我的猜测是,它们都有优点和缺点,我的目标是准确地找出它们是什么,以便在现实场景中避免/利用它们。

    8 回复  |  直到 11 年前
        1
  •  57
  •   Brad Larson    16 年前

    Mike Ash在他的帖子中有一些用于执行ObjuleC方法调用和C和C++的硬数。 "Performance Comparisons of Common Operations" . 也, this post 在使用Objective-C++调整iPhone应用程序性能方面,Savoy软件是一本有趣的书。

    比起Objective-C+,我更喜欢Objective-C的干净的描述性语法,并且没有发现语言本身是我的性能瓶颈的根源。我甚至倾向于做一些我知道会牺牲一点性能的事情,如果它们使我的代码更易于维护的话。

        2
  •  55
  •   justin    11 年前

    是的,写得好的C++速度要快得多。如果你写的是性能关键的程序,而C++的速度不如C(或者只有百分之几),那就有问题了。如果您的objc实现和c一样快,那么 通常 错误——也就是说,程序很可能是objc ood的一个坏例子,因为它可能使用一些“肮脏”的技巧,在它所操作的抽象层下面跨一步,例如直接的ivar访问。

    Mike Ash的比较是非常误导的——我永远不会推荐比较你编写的程序的执行时间的方法,或者推荐它来比较C与C++和Objc。所给出的结果是通过使用编译器优化的测试提供的。 残疾人 . 在测量执行时间时,禁用优化编译的程序很少相关。将其视为比较C++与Objule-C的基准是有缺陷的。测试还比较了单个特性,而不是整个现实世界的优化实现——单个特性以非常不同的方式与两种语言组合在一起。这与优化实现的实际性能基准相差甚远。示例:使用优化 启用 , IMP 缓存和虚拟函数调用一样慢。静态调度(与动态调度相反,例如使用 virtual 以及对已知C++类型的调用(其中可以动态绕过动态调度)可以被积极地优化。这个过程被称为非虚拟化,当它被使用时,一个成员函数被声明 事实上的 甚至可能 inline d.在Mike Ash测试中,对已声明的成员函数进行了多次调用。 事实上的 并且有空的主体:这些调用被优化掉了 完全地 当类型是已知的,因为编译器看到了实现,并且能够确定动态调度是不必要的。编译器还可以消除对 malloc 在优化的版本中(支持堆栈存储)。因此,在C、C++或Objtovi-C中启用编译器优化会在执行时间上产生巨大的差异。

    这并不是说所呈现的结果是完全无用的。如果您想确定外部API的使用时间之间是否存在可度量的差异,可以获得一些关于外部API的有用信息。 pthread_create +[NSObject alloc] 在一个平台或体系结构上。当然,这两个示例将在您的测试中使用优化的实现(除非您碰巧在开发它们)。但是,对于在编译程序中将一种语言与另一种语言进行比较,如果禁用优化,则显示的结果是无用的。

    对象创建

    还可以考虑在objc中创建对象-每个对象都是动态分配的(例如在堆上)。使用C++,对象可以在堆栈上创建(例如,如创建C结构和在许多情况下调用简单函数一样快)、堆上或抽象数据类型的元素。每次分配和释放(例如通过malloc/free)时,都可以引入一个锁。当在堆栈上创建C结构或C++对象时,不需要锁(尽管内部成员可以使用堆分配),它通常只需要少量指令或少量指令加上函数调用。

    此外,objc对象是引用计数的实例。对象的实际需要是 std::shared_ptr 在性能关键方面,C++是非常难得的。C++中没有必要或不希望每个实例都是共享的、引用计数的实例。您对C++的所有权和寿命有更多的控制权。

    数组和集合

    数组和C和C++中的许多集合也使用强类型容器和连续内存。由于下一个元素成员的地址通常是已知的,所以优化器可以做更多的工作,并且您有很好的缓存和内存位置。有了objc,对于标准对象(例如 NSObject )

    派遣

    关于方法,许多C++实现使用很少的虚拟/动态调用,特别是在高度优化的程序中。这些是静态方法调用和优化器的素材。

    对于objc方法,每个方法调用(objc消息发送)都是动态的,因此是优化器的防火墙。最终,在编写性能关键的objc时,这会导致许多限制或不便,这些限制或不便会影响到您可以和不能将性能保持在最低水平。这可能导致更大的方法、IMP缓存、频繁使用C。

    某些实时应用程序无法使用 任何 objc消息传递在它们的呈现路径中。无——音频渲染就是一个很好的例子。objc调度仅仅是不为实时目的而设计的;当消息传递对象时,分配和锁定可能发生在后台,这使得objc消息传递的复杂性/时间变得不可预测,以至于音频呈现可能会错过它的最后期限。

    其他特征

    C++还为其许多库提供泛型/模板实现。这些优化非常好。它们是类型安全的,并且可以使用模板进行大量的内联和优化(考虑在编译时发生的多态性、优化和专门化)。C++在严格Objc中添加了一些不可用或可比较的特征。尝试直接比较非常不同的语言、对象和库并没有那么有用——它只是实际实现的一个很小的子集。考虑到设计和实现的许多方面,最好将问题扩展到库/框架或真正的程序。

    其他点

    C和C++符号在构建的各个阶段(剥离、死代码消除、内联和早期内联,以及链接时间优化)中可以更容易地被移除和优化。这样做的好处包括减少二进制大小、减少启动/加载时间、减少内存消耗等。对于一个应用程序来说,这可能不是什么大问题;但是如果你重用了大量的代码,而且你应该这样做,那么你的共享库可能会给程序增加很多不必要的负担,如果实现了objc——除非你准备跳过一些火热的箍环。因此,可伸缩性和重用也是中/大型项目以及重用率较高的组中的因素。

    包含的库

    objc库实现者也针对环境进行了优化,因此其库实现者可以利用一些语言和环境特性来提供优化的实现。虽然在纯objc中编写优化程序时存在一些相当重要的限制,但cocoa中存在一些高度优化的实现。这是可可的一个优点,尽管C++标准库(有些人称之为STL)也没有懈怠。可可比C++更高层次的抽象——如果你不清楚你在做什么(或者应该做什么), 靠近金属的操作会让你付出代价 . 如果您不是某个领域的专家,那么回归到一个好的库实现是一件好事,除非您真的准备好学习。此外,Cocoa的环境是有限的;您可以找到更好地利用操作系统的实现/优化。

    如果你正在编写优化程序,并且在C++和Objc中都有这样的经验, 清洁的 C++的实现通常会比快或快两倍。 清洁的 objc(是的,你可以和cocoa比较)。如果你知道如何优化,你通常可以做得比高级的、通用的抽象更好。虽然,一些优化的C++实现将比COCOA的快或慢(例如,我在文件I/O上的最初尝试比COCOA慢),主要是因为C++实现初始化了它的内存。

    很多问题都归结于你熟悉的语言特性。我使用两种语言,它们都有不同的优势和模型/模式。它们相辅相成,而且都有很好的图书馆。如果你正在执行一个复杂的、性能关键的程序,正确使用C++的特性和库将给你更多的控制,并为优化提供显著的优势,这样在右手中,“快几倍”是一个很好的默认预期(不要期望每次都赢,或者没有一些工作)。记住,要理解C++足够好,才能真正达到这一点。

    我将大部分性能关键路径保持为C++,但也认识到Objc也是一些问题的非常好的解决方案,并且有一些非常好的库可用。

        3
  •  31
  •   Johan Kotlinski    14 年前

    收集“硬数据”是非常困难的,因为这并没有误导。

    像您建议的那样,进行特性到特性的比较最大的问题是这两种语言鼓励非常不同的编码风格。Objto-C是一种动态的语言,带有鸭式输入,其中典型的C++用法是静态的。同一个面向对象的体系结构问题可能会有非常不同的理想解决方案,使用C++或ObjaveC。

    我的感觉(就像我在两种语言中编程,主要是在巨大的项目上):为了最大化ObjuleC的性能,它必须被写得非常接近C。然而,用C++,可以比C更有效地使用语言而没有任何性能损失。

    哪一个更好?我不知道。对于纯粹的性能,C++总是有优势的。但是Objective-C的OOP风格确实有其优点。我肯定认为用它来保持一个健全的建筑会更容易。

        4
  •  7
  •   Grant Peters    14 年前

    一般来说,这并不是可以回答的问题,因为它真正取决于您如何使用语言功能。两种语言都会有它们擅长的东西,它们擅长的东西,以及有时快有时慢的东西。这真的取决于你使用什么以及你如何使用它。唯一可以确定的方法是分析代码。

    在Objic C中,你也可以编写C++代码,所以在大多数情况下,在目标C中代码可能更容易,如果你发现一些不好的东西,那么你可以写一个C++版本,看看它是否有帮助(C++在编译时倾向于更好地优化)。如果与之接口的API也在其中编写,那么目标C将更易于使用,而且您可能会发现OOP的风格更容易或更灵活。

    最后,您应该按照您知道的方式编写安全、可靠的代码,如果您找到了一个需要其他语言特别关注的领域,那么您可以切换到这个领域。X代码允许您在同一个项目中编译这两个代码。

        5
  •  3
  •   memo    14 年前

    我在iPhone3G上做了几次测试,几乎是两年前的事了,那时候没有文档或硬数字。不确定它们是否仍然有效,但源代码已发布并附加。

    这不是一个非常广泛的测试,我主要对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的迭代,而是消息的发送。我想尝试方法选择器,并直接调用这些方法,以查看差异有多大,但一直没有得到解决。根据MikeAsh的标准,它的速度快了5倍多。

        6
  •  3
  •   Wolfgang Schreurs    13 年前

    我没有用于目标C的硬数据,但我确实有一个寻找C++的好地方。

    C++在Bjarne Stroustroup早期的反思中以C类的形式从C开始 http://www2.research.att.com/~bs/hopl2.pdf 因此,C++可以被认为(类似于目标C)将C推到其面向对象的限制。

    这些限制是什么?在1994年至1997年的时间框架中,许多研究人员发现,由于动态绑定,例如C++函数被标记为虚拟的,并且可能有/可能不是覆盖这些功能的子类,因此对象定位会付出代价。(在爪哇和C语言中,所有函数都希望Ctor本质上是虚拟的,而且你不能做很多事情。)在IBM研究公司的研究人员的“Java即时编译器的去虚拟化技术研究”中,他们对比了用于处理这个问题的技术,其中包括Urz Hyl LZle和Gerald Aigner。在Karel Driesen的另一篇论文中,Urz H.L.LZLE表明,在调用虚拟函数(例如VTAB+Tununk)中,平均花费5.7%的时间在C++程序中(最多可达50%)。后来,他与一些SimalTalk研究者合作,结束了Java热点VM来解决OO中的这些问题。这些特性中的一些被备份到C++(例如“保护”和异常处理)。

    正如我提到的,C++是静态类型的,其中目标C是鸭型的。执行中的性能差异(但不是代码行)可能是这种差异的结果。

        7
  •  1
  •   Community CDub    8 年前

    This study 说要在CPU密集型的游戏中真正获得性能,必须使用C。链接的文章完成了一个可以运行的Xcode项目。

    我相信 底线 IS:在必须与iPhone功能交互的地方使用Objective-C(毕竟, putting trampolines everywhere can't be good for anyone 但是,当涉及到循环时,像向量对象类或密集数组访问之类的东西,会用C++ STL或C数组来获得良好的性能。

    我的意思是,看到 position = [[Vector3 alloc] init] ; . 如果使用引用依赖于像位置向量这样的基本对象,那么您只需要一个性能命中。

        8
  •  -1
  •   Community CDub    8 年前

    对。C++在性能/ Expsisith/Read权衡中占绝对优势。

    “我在寻找硬数据,而不是福音主义”。谷歌是你最好的朋友。

    1. Obj-C NSCOPE与苹果公司的C++进行了交换。在资源受限的设备中,只有C++才把它作为主流的面向对象编程语言。 NSString stringWithFormat is slow

    2. Obj-C OOP抽象被分解为基于过程的C结构,否则,数量级比Java慢。作者还知道消息缓存——但还没有开始。因此,用C++在OOP中建模大量的小玩家/敌人对象,或者,用Obj-C围绕一个简单的OOP包装器的许多过程结构,可以有一个等价于过程+面向对象编程= Obj-C的范例。 http://ejourneyman.wordpress.com/2008/04/23/writing-a-ray-tracer-for-cocoa-objective-c/