在运行时源码(objc4-723版本)中,当向对象发送消息时,运行时可以通过两种方式搜索方法:
/***********************************************************************
* getMethodNoSuper_nolock
* fixme
* Locking: runtimeLock must be read- or write-locked by the caller
**********************************************************************/
static method_t *search_method_list(const method_list_t *mlist, SEL sel) {
int methodListIsFixedUp = mlist->isFixedUp();
int methodListHasExpectedSize = mlist->entsize() == sizeof(method_t);
if (__builtin_expect(methodListIsFixedUp && methodListHasExpectedSize, 1)) {
return findMethodInSortedMethodList(sel, mlist);
} else {
// Linear search of unsorted method list
for (auto& meth : *mlist) {
if (meth.name == sel) return &meth;
}
}
#if DEBUG
// sanity-check negative results
if (mlist->isFixedUp()) {
for (auto& meth : *mlist) {
if (meth.name == sel) {
_objc_fatal("linear search worked when binary search did not");
}
}
}
#endif
return nil;
}运行时将判断方法列表是否排序,并选择线性搜索或二进制搜索。
如果方法列表是排序的,显然二进制搜索更好,否则它应该是线性搜索。
所以我的问题是,在什么情况下,一个类中的方法将被排序?
什么时候对它们进行排序?谁干的?
发布于 2018-12-04 09:02:15
看看isFixedUp标志何时设置为true。
https://opensource.apple.com/source/objc4/objc4-706/runtime/objc-runtime-new.mm.auto.html
基本上,当一个进程启动时,dyld和运行时都有“修复”阶段,它们将符号绑定在一起,优化一堆东西,或者为应用程序的运行做好准备。
ObjC的链接地址查找阶段可以优化方法列表的布局,使后续的查找速度更快。特别是,链接地址信息将确保每个选择器都是唯一的;即一个对象的layoutSubviews方法的选择器将与另一个对象的选择器按位相同,而不仅仅是指向同一个char*的两个副本。它还对列表进行排序,这可能也会使查找速度更快。
一旦解决了这个问题,方法查找就可以快速进行(调用findMethodInSortedMethodList)。如果没有修复,则运行时执行线性搜索(如该代码所示)。
https://stackoverflow.com/questions/53581451
复制相似问题