OBJC_PRINT_VTABLE_IMAGES 和 OBJC_PRINT_VTABLE_SETUP 不显示任何输出
OBJC_PRINT_VTABLE_IMAGES and OBJC_PRINT_VTABLE_SETUP does not show any output
我尝试在 Objective-C 可执行文件上使用 OBJC_PRINT_VTABLE_IMAGES 和 OBJC_PRINT_VTABLE_SETUP 环境变量,以了解 Objective-C 对象中的 vtable 机制。不幸的是,提到的环境变量对控制台输出没有影响,尽管运行时承认变量已设置:
» OBJC_PRINT_OPTIONS=1 OBJC_PRINT_VTABLE_IMAGES=YES /Applications/TextEdit.app/Contents/MacOS/TextEdit
objc[41098]: OBJC_PRINT_OPTIONS is set
objc[41098]: OBJC_PRINT_VTABLE_IMAGES is set
我尝试在系统 (TextEdit) 和我自己提供的可执行文件上使用这两个变量。没有效果。
Objective-C 对象中的整个 vtable 机制是模糊的。很难在 Apple 页面上找到有关此机制的信息。有一些来自其他来源的信息,但没有官方文档:
http://www.sealiesoftware.com/blog/archive/2011/06/17/objc_explain_objc_msgSend_vtable.html
http://cocoasamurai.blogspot.com/2010/01/understanding-objective-c-runtime.html
为什么这些变量不起作用?当前版本 Objective-C 中的 vtable 是否已弃用?
在这种情况下,答案非常简单 - vtable 调度在 objective-c 运行时不再优化,一开始可能是个坏主意。
基于 vtable 的调度是在 objective-c 运行时加速频繁调用的首次尝试之一,但请注意,它早于当前的方法缓存解决方案。在 vtable 解决方案中使用一组固定的选择器的问题不仅意味着在运行时 中 每个 class 增加内存,而且还意味着如果你正在使用一种不会导致 isEqualToString:
被频繁调用的体系结构,例如,您现在在运行时有一个完全浪费的指针 EVERY class 覆盖了一个那些选择器。哎呀
此外,请注意 Vtable 调度设计不能在 32 位架构上工作,这意味着一旦 iOS SDK 发布,32 位再次成为 objective-c 的合理目标, 这种优化根本行不通。
我能找到的相关文档在 objc-abi.h
:
#if TARGET_OS_OSX && defined(__x86_64__)
// objc_msgSend_fixup() is used for vtable-dispatchable call sites.
OBJC_EXPORT void objc_msgSend_fixup(void)
__OSX_DEPRECATED(10.5, 10.8, "fixup dispatch is no longer optimized")
__IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
如今,运行时中已不存在许多 vtable 调度的残余片段。对代码库的快速 grep 显示 objc-runtime-new.mm
:
中的一些地方
#if SUPPORT_FIXUP
// Fix up old objc_msgSend_fixup call sites
for (EACH_HEADER) {
message_ref_t *refs = _getObjc2MessageRefs(hi, &count);
if (count == 0) continue;
if (PrintVtables) {
_objc_inform("VTABLES: repairing %zu unsupported vtable dispatch "
"call sites in %s", count, hi->fname());
}
for (i = 0; i < count; i++) {
fixupMessageRef(refs+i);
}
}
ts.log("IMAGE TIMES: fix up objc_msgSend_fixup");
#endif
和
*********************************************************************
* fixupMessageRef
* Repairs an old vtable dispatch call site.
* vtable dispatch itself is not supported.
**********************************************************************/
static void
fixupMessageRef(message_ref_t *msg)
这很清楚地表明它不受支持。
另请参阅它的方法存根(如果您在没有编译器生成的调用站点的情况下执行此操作),可在 objc-msg-x86_64.s
:
中找到
ENTRY _objc_msgSend_fixup
int3
END_ENTRY _objc_msgSend_fixup
其中 int3
是 SIGTRAP 指令,如果未附加调试器(通常)会导致崩溃。
因此,虽然 vtable dispatch 在 objective-c 的历史上是一个有趣的记录,但在我们还不太熟悉优化通用方法的最佳方法时,它应该只是一个实验而已来电。
我尝试在 Objective-C 可执行文件上使用 OBJC_PRINT_VTABLE_IMAGES 和 OBJC_PRINT_VTABLE_SETUP 环境变量,以了解 Objective-C 对象中的 vtable 机制。不幸的是,提到的环境变量对控制台输出没有影响,尽管运行时承认变量已设置:
» OBJC_PRINT_OPTIONS=1 OBJC_PRINT_VTABLE_IMAGES=YES /Applications/TextEdit.app/Contents/MacOS/TextEdit
objc[41098]: OBJC_PRINT_OPTIONS is set
objc[41098]: OBJC_PRINT_VTABLE_IMAGES is set
我尝试在系统 (TextEdit) 和我自己提供的可执行文件上使用这两个变量。没有效果。
Objective-C 对象中的整个 vtable 机制是模糊的。很难在 Apple 页面上找到有关此机制的信息。有一些来自其他来源的信息,但没有官方文档: http://www.sealiesoftware.com/blog/archive/2011/06/17/objc_explain_objc_msgSend_vtable.html http://cocoasamurai.blogspot.com/2010/01/understanding-objective-c-runtime.html
为什么这些变量不起作用?当前版本 Objective-C 中的 vtable 是否已弃用?
在这种情况下,答案非常简单 - vtable 调度在 objective-c 运行时不再优化,一开始可能是个坏主意。
基于 vtable 的调度是在 objective-c 运行时加速频繁调用的首次尝试之一,但请注意,它早于当前的方法缓存解决方案。在 vtable 解决方案中使用一组固定的选择器的问题不仅意味着在运行时 中 每个 class 增加内存,而且还意味着如果你正在使用一种不会导致 isEqualToString:
被频繁调用的体系结构,例如,您现在在运行时有一个完全浪费的指针 EVERY class 覆盖了一个那些选择器。哎呀
此外,请注意 Vtable 调度设计不能在 32 位架构上工作,这意味着一旦 iOS SDK 发布,32 位再次成为 objective-c 的合理目标, 这种优化根本行不通。
我能找到的相关文档在 objc-abi.h
:
#if TARGET_OS_OSX && defined(__x86_64__) // objc_msgSend_fixup() is used for vtable-dispatchable call sites. OBJC_EXPORT void objc_msgSend_fixup(void) __OSX_DEPRECATED(10.5, 10.8, "fixup dispatch is no longer optimized") __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
如今,运行时中已不存在许多 vtable 调度的残余片段。对代码库的快速 grep 显示 objc-runtime-new.mm
:
#if SUPPORT_FIXUP // Fix up old objc_msgSend_fixup call sites for (EACH_HEADER) { message_ref_t *refs = _getObjc2MessageRefs(hi, &count); if (count == 0) continue; if (PrintVtables) { _objc_inform("VTABLES: repairing %zu unsupported vtable dispatch " "call sites in %s", count, hi->fname()); } for (i = 0; i < count; i++) { fixupMessageRef(refs+i); } } ts.log("IMAGE TIMES: fix up objc_msgSend_fixup"); #endif
和
********************************************************************* * fixupMessageRef * Repairs an old vtable dispatch call site. * vtable dispatch itself is not supported. **********************************************************************/ static void fixupMessageRef(message_ref_t *msg)
这很清楚地表明它不受支持。
另请参阅它的方法存根(如果您在没有编译器生成的调用站点的情况下执行此操作),可在 objc-msg-x86_64.s
:
ENTRY _objc_msgSend_fixup int3 END_ENTRY _objc_msgSend_fixup
其中 int3
是 SIGTRAP 指令,如果未附加调试器(通常)会导致崩溃。
因此,虽然 vtable dispatch 在 objective-c 的历史上是一个有趣的记录,但在我们还不太熟悉优化通用方法的最佳方法时,它应该只是一个实验而已来电。