ios - 在进行选择器调用之前显式检查nil是否有任何好处?

标签 ios objective-c performance

我看过这样的代码:
if (myObject && [myObject mySelector]) ...
我听说这可以防止不必要的选择器查找和防止将选择器消息发送到对象指针的方法调用,该对象指针在运行时为nil。

但是,我认为Objective-C的核心原则是所有对nil个对象的选择器调用都返回nil,因此我希望就编译器而言,这可以得到很好的优化。

有谁知道这种模式在性能方面是否真的有优势?

最佳答案

有谁知道这种模式在性能方面是否真的有优势?

标准答案:在所有情况下都无法区分

真实答案:需要更多指令并跳转,会有一些性能差异,并且如果您在需要的地方编写代码类型,您将知道这是否是一个重要的差异–否则您将不会编写这种类型的代码代码!

我只是好奇答案:好奇心很好,要保持好奇心!使用标准Xcode模板编写一个非常简单的程序。首先,使用方法MyObject添加一个mySelector类,返回类型long,该方法将1L返回到AppDelegate.m文件。

现在在AppDelegate实现内部编写一个小的测试方法,类似于:

- (int) test:(MyObject *)myObject
{
   if (myObject && [myObject mySelector])
      return 42;
   else
      return 24;
}

然后在applicationDidFinishLaunching中添加一些代码以调用test,同时传递nil以及MyObjectNSLog的实例作为返回值。

运行。

现在转到**产品->执行操作->组装“AppDelegate.m”。这将产生一个生成的汇编语言的列表。该列表的底部是一个菜单,您可以通过该菜单选择构建的类型,从而选择汇编代码的优化方式。 “运行”几乎没有优化,是在开发和调试时使用的,“归档”显示了构建最终应用程序时产生的优化代码。

如果查看程序集(如果您不知道x86代码,请不要担心指令名称会提示它们的含义),您会发现nil的初始测试是两条指令:compare&jump(为else分支编码) 。之后是用于消息调用的代码:将作为myObject和选择器的参数加载到寄存器中,再调用objc_msgSend,然后进行比较并跳转以测试其返回值。

您看不到objc_msgSend做什么,因为那不是您的代码。要发现这一点:在if上放置一个断点,然后运行。停止时打开助手编辑器并将其设置为显示反汇编–您现在将在左侧面板中具有Objective-C代码,在右侧面板中具有匹配的汇编代码。

这两个面板下面是调试控件,如果将鼠标悬停在它们上方,将弹出暂停工具提示,以解释每个控件的功能。找到“单步执行”并按住控制键并单击,如工具提示所言,这是“单步执行指令”,并将一次遍历代码中的一条指令,而不是Objective-C源代码行。重复按Control键并单击,直到右面板显示您已进入objc_msgSend

现在查看objc_msgSend程序集,您将看到它以nil的compare&jump开头,如果按照跳转的位置进行操作,则有指令清除四个寄存器,然后返回。

因此,如果没有在nil中进行初始if测试,则该代码将加载两个参数寄存器,跳转到objc_msgSend,进行比较,测试,清除4个寄存器,然后返回您的代码,然后对返回值进行比较和跳转。

nil情况中,这显然是更多关于的指令。

但是nil案例需要进行if的比较和跳转,这是不必要的...因此,“性能更好的明智选择”将取决于nil和non- nil值的统计分布,具体取决于代码...而且请记住,现代机器每秒执行数百万条指令,并且具有分支谓词和缓存之类的功能,即使代码跳跃时也可以使执行快速进行...

希望到目前为止,您的好奇心已使您理解了上面的“标准答案”,并给了您有关代码和应用程​​序领域的提示,在这些方面可能会对性能产生实际的影响。

因此,如果您认为初始测试明确了代码的目的,请包括它,否则不要这样做。您的代码可能会运行得更快或更慢,但是您不会注意到任何一种方式,除非计算纳秒级会对您的应用程序区域产生影响。

保持好奇心!

关于ios - 在进行选择器调用之前显式检查nil是否有任何好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62183038/

相关文章:

具有不同语言的 iPhone 应用程序

ios - 从 iPhone 检索 UDID 的注册挑战

iphone - 有没有办法在iPhone的UITabBarController中设置第四个选项卡的更多选项卡

ios - Watchkit:以编程方式设置全局色调

iphone - 如何让 UIImageView 告诉我它的动画何时停止?

c - 快速浮点abs函数

iphone - initWithNibName : bundle: always load English nib

objective-c - 所有对象占用的内存量都相似吗? Objective-c

c++ - 为什么我的程序很慢?我怎样才能提高它的效率?

c# - 慢 DeterminePostBackMode()