我正在比较不同的编程语言和开发平台。Objective-c 和其他语言的一个重要区别是它使用选择器、消息,所以每次都调用 objc_msgSend,跨越共享库的边界,因此引入了可测量的开销,加上 objc_msgSend 的更多开销(在缓存的情况下很少)内部运作,就像这里解释的那样:http: //www.mulle-kybernetik.com/artikel/Optimization/opti-3.html 我不是专家,所以我必须相信这篇文章,在这个论坛上找到。在 Apple 官方指南中,我发现“点语法”只是“语法糖”,即使用了相同的方法调用机制。问题:我想知道,如果在类实例中执行纯调用,那么调用 objc_msgSend 将是一种浪费。也就是从同一个类实例的方法调用一个类实例的方法。谢谢
3 回答
在假设的 OOP 语言中考虑这种情况:
class A {
say_something(){
print("A!")
}
do_something(){
say_something()
}
}
和
class B : extends A {
say_something(){
print("B!")
}
}
现在假设您有一个 , 的实例B
并调用do_something
:
B b;
b.do_something();
应该b
打印A
还是B
?say_something
如果在实现中的调用do_something
通过vtable
(在 C++ 中)或obj_msgSend
(在 Obj-C 中),它将打印B
,但如果编译器决定对同一类中的方法的调用应该调用同一类中的方法,它将打印A
。
哪个是可取的取决于具体情况。因此,在 C++ 中,您可以选择是否标记成员函数virtual
。在 Objective-C 中,每个方法都是虚拟的。
因此,即使在 C++ 中,您建议的优化也不会针对虚拟方法进行。我不会说没有虚拟方法的语言是正确的 OOP 语言。
无论如何,现在您可能会担心它会降低 Obj-C 应用程序的性能。苹果知道危险,所以他们有很多很多的优化。例如,在最近的运行时中,objc_msgSend
它位于一个固定地址,因此您不需要首先通过共享库边界。
Mulle-Kybernetic 的文章也不错,但请注意它已经过时了:它是十年前的事了,这在这个行业是史前时代。objc_msgSend
您可以在bbum 的博客文章或Hamster 的博客文章中了解最近对实现的优化。
如果您正在编写管理 UI 的代码,那么使用标准消息传递(即objc_msgSend
幕后)就足够了。它甚至在移动设备上运行非常流畅!因此,不要通过获取IMP
等来进行过早的优化,直到在测量代码的性能后证明是绝对必要的。
如果您正在编写一个计算密集型代码,例如涉及数以万计的粒子移动,是的,我建议您不要使用 Obj-C 消息传递框架。在这种情况下,只需简单地编写 C 代码(可以在 Objective-C 中使用)或 C++ 代码(可以在 Objective-C++ 中使用)。
所有的 Objective-C 方法调用都使用 obj_msgSend。这是因为代码不知道实际的真实类是self
. 即:它可以是具有另一个实现的子类,甚至可以是远程机器通过 xmlrpc 实现的方法的代理。
AFAIK 如果您知道要经常向对象 Y 发送消息 X,您可以通过获取给定对象的选择器的实现来自己优化事情。
它仍然通过 objc_msgSend 和变体使用动态调度。
理想情况下,将为 objc 类型生成类似于 JIT 的东西。
与 objc 不同,c++ 编译器可以使用静态调度来调用 c++ 类型,当它可以确定类型时,这些类型被标记为虚拟。
无论如何,有很多优化方法——你可以从用 c++ 实现开始,然后在真正方便的地方使用 objc ......但我不确定你到底想要完成什么。