【问题标题】:Objective-C vs. C speedObjective-C 与 C 速度
【发布时间】:2012-03-12 14:15:18
【问题描述】:

这可能是一个幼稚的问题,但我还是会问。

我正在 iOS 上使用 Core Audio (C API) 并将 C 与 Objective-C 混合。我的班级有 .mm 扩展名,到目前为止一切正常。

我在不同的地方读到过关于 Objective-C 速度慢的文章(没有给出太多细节——我也没有做出任何声明)。我了解不从 Core Audio 渲染回调等调用 Objective-C 以及原因。

另一方面,我需要从我的 GUI 调用处理 Core Audio 内容的类,以便在运行时进行各种调整。会有一些阵列的移动,主要是移动Core Audio使用的数据。在 C 中编写我的函数并将我的变量存储在向量中而不是 NSMutableArrays 中,在速度方面会有什么好处吗?

我只使用 Objective-C/iOS 几个月,所以我对此没有任何看法。

【问题讨论】:

  • 如果CoreAudio是一个C API,那你为什么要把它编译成一个Objective-C++文件呢?
  • 同意。只需要一个简单的 Objective-C 文件即可。
  • 我使用 std:vector 而不是 NSArray (认为它们会更快)- 所以我需要 .mm 才能编译它。也许我不需要使用 std:vector。
  • Is C++ faster than Objective-C? 的可能重复项

标签: objective-c c ios


【解决方案1】:

Objective-C 比直接调用 C 函数稍慢,因为它的动态特性涉及查找。如果没有其他人添加详细信息,我将在稍后编辑此答案,详细说明其工作原理。

但是,更重要的是,您过早地进行了优化。 Objective-C 的额外开销对您的应用程序性能的显着影响为零的可能性非常

利用 Objective-C 的优势来设计最好的书面、最面向对象的应用程序。当且仅当测试显示性能问题时,才优化应用程序的这些特定区域。

【讨论】:

  • 我投了赞成票,但我也会发表评论以强调这是多么重要。早期优化没有意义。
  • 谢谢 - 这听起来是个好建议。我只是想避免走一条已知的“较慢的道路”,所以我想我会问。
  • 我完全同意,尽管 Core Audio 是纯 C 代码可以发挥作用的领域之一。每秒运行 44,100 个音频样本(在 16 位立体声中为 176,400 字节),只需几个方法调用就可以让较旧的 iDevice 崩溃。见mikeash.com/pyblog/why-coreaudio-is-hard.html
  • 你在 Instruments 中分析它并在顶部看到 objc_msgSend 时就会知道...否则我不会担心。
  • 如果您确实发现objc_msgSend 在内部循环中消耗了大量时间,例如,您可以通过查找大量使用的方法的实现函数 (IMP) 来优化它,并且然后直接调用它们。
【解决方案2】:

Objective-C 的主要性能损失在于调度方法调用所需的工作。 Objective-C 是动态绑定的,这意味着接收消息的对象(选择器)在运行时决定如何处理它。这是通过哈希表实现的。选择器被散列(我认为是在编译时)并映射到通过散列表调用的方法,并且查找需要时间。

话虽如此,发生在objc_msgSend() 中的方法查找是高度优化的。事实上,它是用汇编程序手工制作的。我听说它与 C 函数调用相比的开销约为 20 条机器指令。通常,这没什么大不了的,但是如果您正在运行 100,000 个元素 NSArray,则使用 -objectAtIndex: 查找每个元素会产生相当大的开销。

然而,几乎在所有情况下,额外的灵活性和功能都是值得的。这就是为什么 wadersworld 的回答包含很好的建议。

Bill Bumgarner 写了一组很棒的articles on objc_msgSend()

【讨论】:

    【解决方案3】:

    慢是相对的。

    Objective C 消息传递相对于访问最内层循环中的许多小数据类型元素(大图像位图中的每个像素或整首歌曲中的每个音频样本)。相对于以 UI 甚至显示刷新事件的速度执行任何操作,Objective C 确实快速

    对于处理 Core Audio 原始样本,坚持使用 C。对于处理与 UI 相关的 Core Audio 事件(停止、启动、属性等),将它们封装在 Objective C 中不会产生任何可测量的速度差异。

    【讨论】:

      【解决方案4】:

      虽然其他答案已经量化了动态方法调度 (objc_msgSend),手动调整的汇编增加了大约 20 条机器指令,但与 C 相比,Objective-C 的性能较差的另一个可能原因是:Objective-C 具有更丰富的基础图书馆。

      一个这样的性能比较有一个游戏生成地形,如下所示:

      • 纯 C 版本提供 60 fps
      • objective-C 版本提供 39 fps

      速度变慢的原因是使用的 NSMutableArray 包括各种安全检查,并且能够增长和缩小到所需的大小,而 C 数组是固定大小的 - 如果超出范围,请继续写入你想要,只是为坏事的发生做好准备。

      幸运的是,正如其他人所说,稍后进行性能分析非常容易,并在需要计算的地方换入一些纯 C 代码。

      【讨论】:

        【解决方案5】:

        Objective-C 并不慢,它实际上是带有对象的 C。

        Objective-C 中的一个类由几个不同的东西组成:

        • 选择器到函数的映射(方法实现)
        • 名称到类型(实例变量)的映射
        • 名称到类型和函数(属性)的映射

        因此,Objective-C 将与您自己调用原始 C 函数一样快,但查找函数会产生一点开销。

        【讨论】:

        • @Goz 在 x86 上的开销约为 8-10 个周期,在 ARM 上约为 10-15 个周期。所以,“一点”是正确的。
        • 有人用 C 和 obj-C 对递归函数进行了基准测试。 goo.gl/hFXN1I。由于函数调用本身的相对简单的性质,您看到的更多开销是通过 C 函数调用的 obj-c 消息传递......这相当繁重......也就是说,调用内部执行的工作越多,开销就越小...所以 YMMV 和所有类似的东西。
        • @Goz 显然,必须使用一些逻辑。如果这个小开销是瓶颈,ObjC 的灵活性允许您将其转换为 C++ 或 C。这不是“一刀切”的交易,这就是语言的美妙之处在于您可以轻松地使用其他语言它。
        • 我建议值得添加到您的答案中;)
        • @Goz 我认为其他答案足以涵盖该主题,我认为没有真正的理由再次将其放到首页,并在此处获得更多重复的答案。
        【解决方案6】:

        目标 c 像 c 一样快 因为没有目标 C 编译器,所有目标 C 代码都使用结构和函数指针解析为 C。 Objective C是我们用C编写面向对象编程的方式。面向对象编程语言(Objective C中的Small Talk)的所有特性都是使用C实现的。 实际上,我们可以通过使用结构(可以具有类的实例变量)和操作该数据的相关函数在 C 中定义一个对象。消息传递或调用对象函数是使用函数完成的

        objc_msgSend(receiver,selector,arg1,arg2....)
        

        即C,Objective C处理器提供Objective C。当我们编译Objective C代码时,它被转换为纯C,C代码被编译并运行。 C 和 Objective C 的区别在于速度。

        【讨论】:

        • 但是此调用需要在方法表中执行动态查找,并且每次调用该方法时。另一方面,C 执行静态调度。静态调度要快得多。调用 C 函数比调用 Obj-C 方法快大约 3-6 倍,那么它们怎么能同样快呢?如果你从不调用 Obj-C 中的方法,它们只能同样快,但有些方法违背了使用 Obj-C 的目的。
        【解决方案7】:

        这一切都取决于你在做什么。使用核心音频,无论如何都应该将 99% 的执行时间花在库函数上。现在,如果你做了一些愚蠢的事情——取第二个样本,将每个样本变成一个 NSNumber,将它们存储到一个 NSMutableArray 中,并通过调用 [[myArray objectAtIndex:i] doubleValue] 进行手写 FFT,你会得到你应得的.最慢的 iPhone 每微秒可以执行很多方法调用。

        无论您使用 C 函数还是 Objective-C 方法都没有区别。唯一的区别是你调用了多少个 Objective-C 方法。许多微小的 Objective-C 方法被调用一百万次是很多开销。并且没有法律禁止在 Objective-C 代码中使用 C 数组。

        加快速度的规则:使用仪器。测量执行时间。选择执行时间长的地方,加快速度,再次测量。大多数时候,你不会通过用更好的代码替换好的代码来获得加速,而是用相当好的代码替换大量愚蠢的代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多