Ios 在进行选择器调用之前显式检查nil有什么好处吗?
我见过这样的代码:Ios 在进行选择器调用之前显式检查nil有什么好处吗?,ios,objective-c,performance,Ios,Objective C,Performance,我见过这样的代码: if(myObject&&[myObject mySelector])… 我听说这可以防止不必要的选择器查找和方法调用,从而将选择器消息发送到运行时发现为零的对象指针 然而,我认为objective-C的一个核心原则是,对nil对象的所有选择器调用都返回nil,因此我希望它在编译器方面得到了很好的优化 有人知道这种模式在性能方面是否真的有任何优势吗?除了给未来的开发人员一个提示,即nil在那里是可以接受的,它没有任何用途。我希望代码在任何选择器查找发生之前退出 有人知道这种模
if(myObject&&[myObject mySelector])…
我听说这可以防止不必要的选择器查找和方法调用,从而将选择器消息发送到运行时发现为零的对象指针
然而,我认为objective-C的一个核心原则是,对nil对象的所有选择器调用都返回nil,因此我希望它在编译器方面得到了很好的优化
有人知道这种模式在性能方面是否真的有任何优势吗?除了给未来的开发人员一个提示,即
nil
在那里是可以接受的,它没有任何用途。我希望代码在任何选择器查找发生之前退出
有人知道这种模式在性能方面是否真的有任何优势吗
标准答案:在所有可能的情况下,性能无法区分
真正的答案:一个人需要更多的指令和跳跃,就会有一些性能差异,如果你在编写重要的代码类型,你就会知道这是否是一个重要的差异,否则你就不会编写这种代码了
我只是好奇回答:好奇是好的,保持好奇!使用标准Xcode模板编写一个非常简单的程序。首先使用方法mySelector
添加一个类MyObject
,返回类型long
,该方法将1L
返回到AppDelegate.m
文件中
现在在AppDelegate
实现中编写一个小测试方法,类似于:
- (int) test:(MyObject *)myObject
{
if (myObject && [myObject mySelector])
return 42;
else
return 24;
}
然后在applicationdFinishLaunching
中添加一些代码以调用test
并通过nil
和MyObject的一个实例
和NSLog
返回值
运行它
现在转到**产品->执行操作->组装“AppDelegate.m”。这将生成生成的汇编语言列表。在这个列表的底部是一个菜单,允许您选择构建的类型,从而选择汇编代码的优化程度;“运行”几乎没有优化,并且是在开发和调试时使用的,“归档”显示在构建最终应用程序时生成的优化代码
如果您查看程序集(如果您不知道x86代码,请不要担心指令名表明了它们的含义),您将看到nil
的初始测试是两条指令:compare&jump(为else分支编写代码)。之后是消息调用的代码:将参数(即myObject
和选择器)加载到寄存器中,调用objc\u msgSend
,然后进行比较和跳转以测试其返回值
你看不到objc\u msgSend做了什么,因为那不是你的代码。要发现这一点:在if
上放置一个断点,然后运行。当它停止时,打开助手编辑器并将其设置为显示反汇编–现在,您将在左面板中显示Objective-C代码,在右面板中显示匹配的组装代码
这两个面板下面是调试控件,如果将鼠标悬停在它们上面,将弹出工具提示,说明每个面板的作用。找到“单步执行”并按住控制键并单击,因为工具提示显示这是“单步执行指令”,并将一次单步执行一条指令,而不是Objective-C源代码行。重复control+单击,直到右侧面板显示您已进入了objc\u msgSend
现在查看objc\u msgSend
程序集,您将看到它以nil
的比较和跳转开始,如果您遵循跳转的方向,则有清除四个寄存器然后返回的说明
因此,如果在if
中没有初始nil
测试,代码将加载两个参数寄存器,跳转到objc\u msgSend
,比较、测试、清除4个寄存器,然后返回到代码,然后对返回值进行比较和跳转
这显然是nil
案例中的更多说明
但是非nil案例需要在if中进行比较和跳转,这是不必要的。。。因此,“哪个性能更好”取决于nil
和非nil
值的统计分布,这取决于代码。。。请记住,现代机器每秒执行数百万条指令,并且具有分支谓词和缓存等功能,即使在代码跳跃时也能保持快速执行
希望到目前为止,您的好奇心已经让您理解了上面的“标准答案”,并为您提供了代码类型和应用程序领域的提示,在这些领域中,它可能会在性能方面产生实际的影响
因此,如果您认为初始测试澄清了代码的目的,那么就包含它,否则不要包含。您的代码可能运行得更快或更慢,但您不会注意到这两种情况,除非计算纳秒在您的应用程序区域中起到作用
保持好奇心