【问题标题】:Does it make a difference in performance if I use self.fooBar instead of fooBar?如果我使用 self.fooBar 而不是 fooBar,性能会有所不同吗?
【发布时间】:2011-02-24 06:10:43
【问题描述】:

注意:我确切地知道属性是什么。这个问题是关于性能的。

使用 self.fooBar 进行 READ 访问对我来说似乎是浪费时间。不必要的 Objective-C 消息传递正在发生。 getter 通常只是简单地传递 ivar,所以只要非常确定不会编写合理的 getter 方法,我认为绕过这个笨重的家伙是完全可以的。

Objective-C 消息传递比直接调用慢大约 20 倍。因此,如果有一些具有数百个属性的高性能高频代码正在使用中,那么避免不必要的 Objective-C 消息传递可能会大有帮助?

还是我在浪费时间思考这个问题?

【问题讨论】:

    标签: iphone objective-c performance properties


    【解决方案1】:

    没有冒犯,但您可能在浪费时间考虑它。除非您的代码每秒访问该属性数千次,否则您不会看到任何性能差异。

    【讨论】:

      【解决方案2】:

      这种过早的优化真的应该推迟到你真正注意到或测量(使用 Instruments.app)一个真正的问题。

      【讨论】:

      • 好点...我只能估计,但是像这样不必要的属性调用大约有几千个,iPhone 是个慢东西。
      【解决方案3】:

      是的,使用属性获取器比直接访问要慢得多。属性 getter 在 self 类(和类别)之外用于封装很有用,但我认为使用 self.ivar getter 没有任何好处,除非您已将 getter 覆盖为其他东西。

      (你为什么首先使用self.ivar?)

      self.ivarself->ivar 不同的唯一情况是:

      1. 属性是atomicso self.ivar will be similar to

        spin_lock(&ivar_lock);
        id retval = [ivar retain];
        spin_unlock(&ivar_lock);
        return [retval autorelease];
        

        对于id 属性,并且

        spin_lock(&ivar_lock);
        spin_lock(&destination_lock);
        memcpy(&destination, &ivar, sizeof(ivar));
        spin_unlock(&ivar_lock);
        spin_unlock(&destination_lock);
        

        对于一个结构。属性为nonatomic时,两者没有区别。

      2. 当类不是最终类时。类或子类的类别可以将属性 getter 覆盖为其他内容。但我认为覆盖一个具体的属性不是一个好的风格。

      就像其他人所说的那样,除非您测试过 getter 是热点,否则将其改回直接 ivar 访问不会有太大帮助。

      【讨论】:

      • 如果不使用self.ivar改变属性,其他对其进行key-value观察的对象将不会被通知改变。此外,在非 GC 多线程环境中,对 ivars 的直接访问不是线程安全的(读或写)。
      • @JeremyP:OP 要求一个 getter。您可以通过 KVO 观察变化,但这是针对 setter 的。
      • 有时将 getter 用于内部内容是有意义的。示例:您希望在访问 ivar 的情况下发生一些事情。一个例子:设置一个对象或必须存在但现在不存在的东西。但在 99% 的情况下,吸气剂毫无意义。
      • 线程安全注释适用于即使是获取 ivars。此外,也有可能是子类覆盖了 getter。
      • @Jeremy:是的。已更新以包含这些信息。
      【解决方案4】:

      它的效率有点低,但您通常仍然不应该公开您的对象状态。尽管公共成员在大多数 OO 语言中被认为是不好的,但在 Objective-C 中实际上有一个务实的原因:该框架使用您的“getter”和“setter”方法使某些事情自动化,例如内存管理和 KVO 通知。由于从多个地方访问 ivars,每段客户端代码都需要完全理解访问器方法所承担的所有职责,并以完全相同的方式执行这些职责。

      所以这不是“绝对不要访问你自己的 ivars”,而是要确保你完全理解它在特定情况下的含义。

      【讨论】:

      • 差别不大。 KVO 和 Core Data 仍然依赖于访问器方法中的行为,并且每段代码仍然负责处理原始方法中的事情,无论该代码是在同一个类中还是在不同的类中。
      • 内部使用ivar访问与@property/KVC/KVO/Core Data没有矛盾。 (顺便说一句,我没有对你投反对票。)
      【解决方案5】:

      这两者并不是真正可以互换的(好吧,有些时候它们是可以互换的)。在需要时直接访问 ivar,并在需要时使用访问器方法。它可能取决于类层次结构、类的实现、代码是否线程安全等。

      如果是您的代码,所有事情很大程度上取决于您。可能有人想要子类化这个类并编写一个始终返回 @"BOO" 的 -foobar 的自定义实现,但他们发现超类方法 -printFooBar 现在打印 @"hello darling" 因为它打印出变量 foobar 的值而不是self.foobar 返回的值?

      调用访问器方法确实比直接使用变量有更多的开销,但是除了性能之外,还有更多的事情需要考虑。就我个人而言,我发现“始终使用访问器方法”的立场与说“从不使用访问器方法”一样荒谬——这显然是荒谬的。

      【讨论】:

        【解决方案6】:

        有些人可能不同意,但我碰巧喜欢直接访问 ivar 并尽可能绕过整个消息传递业务。我认为这让我的意图更加清晰,因为如果我需要向 getter 发送消息(用于内存管理等),那么我会的。

        【讨论】:

        • 我在一定程度上不同意。如果您的 ivar 支持一个属性,您应该始终使用访问器,除非性能是一个真正的问题或在 init/dealloc 中。原因是直接访问ivar绕过了KVO机制,不是线程安全的。诚然,如果属性被声明为非原子的,它也不是线程安全的。
        • 我在一定程度上不同意这一点。不使用标准 getter 方法不会绕过任何 KVO 机制,并且您不会通过使用原子属性使您的应用程序“线程安全”。
        • @mustISignUp:不,如果没有原子 getter,即使访问要读取的 ivar 也不是线程安全的。
        • 我知道。我说使用原子吸气剂不会给你线程安全。你需要一个比原子锁定变量访问更好的方案。
        猜你喜欢
        • 2019-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        相关资源
        最近更新 更多