【问题标题】:Does C code run faster?C 代码运行得更快吗?
【发布时间】:2013-12-15 08:02:37
【问题描述】:

从 Objective-C 调用 C 代码是否有任何性能提升?

我在某处读到,与使用函数调用的其他语言相比,消息传递速度较慢。因此,如果我从 Objective-C 代码中调用 C 函数,是否可以避免消息传递开销?

在优化性能时,是否建议使用 C 语言编写最关键的函数和过程,而不是使用 Objective-C 对象?

编辑:
鉴于有大量关于过早优化和代码可读性的警告,我想澄清一下,我考虑的不是常规应用程序,而是非常具体的应用程序,例如:

  • 图形
  • 加密或压缩算法。
  • 数学

一般来说,不需要面向对象设计的函数或过程,旨在通过参数多次调用。

【问题讨论】:

    标签: iphone objective-c c performance


    【解决方案1】:

    您编写的代码不太可能针对消息发送的瓶颈进行足够优化。以对您最有意义的方式编写代码,然后使用 Instruments 来分析和优化如果需要。几乎可以肯定,如果你的代码很慢,那将是由于比消息发送更高级别的问题。

    【讨论】:

    • OpenGL ES 是用 C 编码的,不是吗?这是我所说的那种代码的一个很好的例子。
    • 过早优化是万恶之源
    • OpenGL 传统上是用 C 语言编写的,但在许多面向对象语言中都有包装器,包括 Objective-C,它们的性能很好。更重要的是您希望代码的外观,而不是您希望它运行多快。
    • 对于许多应用程序类型,需要对应用程序的算法和数据类型进行早期智能优化,以接近可用的实时响应或帧速率。
    • 虽然避免过早优化的原则是正确的,但在实际产品中有很多情况下,消息传递是一个很大的开销,应该加以处理。您应该强烈避免消息在被调用数千次或更多次的紧密循环中传递。与方法不同的是,可以内联一个小函数,有时代表显着的性能提升(特别是当编译器可以应用二次优化时)。您是正确的,您不应该过早优化,但这并不意味着需要考虑消息发送并不常见。
    【解决方案2】:

    这是一个benchmark,它将消息传递与调用 C 函数进行了比较。以下是调用斐波那契函数的不同实现大约 14 亿次的结果。

    Message Passing 23.495 seconds
    IMP Calling     16.033 seconds
    C Function      9.709 seconds
    

    所以是的,调用 Objective C 方法时会有一些开销。但是,除了在某些情况下,这不会影响您的应用程序的性能。事实上,消息传递仍然比most other operations 更有效,例如浮点除法。

    此外,大多数应用程序在等待用户输入、下载数据等方面花费的时间最多。

    【讨论】:

    • 谢谢,我正要制定自己的基准。我知道我不应该从一开始就采取这种方法。我正在考虑使用多个参数多次调用的函数,例如光线追踪或重量级加密算法。所以这是有道理的。
    • 最后我做了自己的基准测试,也使用递归斐波那契(但不是链接中显示的代码)。 Objective-C,即使使用 C 类型 (long, int) 也比 C 函数慢 2,35 倍。当然,用 C 编写某些东西是非常值得考虑的。
    【解决方案3】:

    是的,建议在性能关键的内部循环(例如实时音频信号处理或图像处理代码)中使用编写良好的纯 C,而不是使用 Objective C。在每帧时间处理数千个单独的音频样本或数百万个图像像素时,使用对象数据类型或消息传递很少有任何好处。所有不需要的方法调度周期只会浪费用户的电池寿命。其他类型的复杂数值模拟和有限元模型(等)也可能受益于保持内部循环简单,以获得编译器优化器的最佳结果。

    但是,每个事件只需要以人类的速度发生几次的更高级别的事情可能不会消耗足够的消息传递开销周期来进行衡量。因此,任何用于提高代码可读性和重用性的抽象都不太可能使用户失去任何性能或电池寿命。

    【讨论】:

      【解决方案4】:

      直接调用 C 函数总是比调用 Obj-C 方法快;但是,正如许多人所指出的,除了对性能敏感的代码之外,它不太可能成为瓶颈。

      但是,您可以扭转这种局面,问为什么要使用较慢的方法? - 反对“过早优化”的法令并不意味着“故意编写糟糕的代码”。

      这是一种平衡,使用方法或函数之间的界限是模糊的,你必须做出选择。两个可能有帮助的端点:

      1. 如果代码要改变对象的状态 - 请使用方法。
      2. 如果代码是自然函数;接受一些输入,产生输出,不操纵状态(有“副作用”);那么函数就有意义了。

      对于介于两者之间的所有点,请自行判断。

      例如,如果您有一个类中的代码需要计算多个位置的金字塔体积,您可以抽象出体积算法:方法还是函数?功能 - 它需要一些值,产生一个值,不改变对象状态。也许更好的是让它成为一个static 函数,它有效地使其对类私有并且不会污染您的应用程序命名空间。如果仅在类内部需要这样的算法作为方法编写是没有好处的 - 我会说这样做是“糟糕的代码”(但这是一个意见!)

      【讨论】:

        【解决方案5】:

        初始消息在运行时被解释,因此比 C++ 虚拟方法调用耗时大约三倍(它本身比直接调用稍慢)。然而,后续调用被 IMP 缓存,并且在大多数实现中比 C++ 虚拟方法调用更快,但仍比直接函数调用(在 C 或 C++ 中)稍慢。

        所以,是的,可能会有性能提升,但在失去 Objective-C 的所有好处之前,您应该确定“优化”的好处是显着的。在大多数情况下,可以在其他地方获得更大的性能优势;例如,通过采用合适的数据结构和算法。大多数代码都花时间做事情而不是函数调用开销 - YMMV。

        Objective C message dispatch mechanism

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-26
          • 2017-08-28
          相关资源
          最近更新 更多