1. Runloop
CFRunLoopRef CFRunLoopGetCurrent(void) {
CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
// 一個 線程 對應(yīng) 一個 runloop
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
-
RunLoop 的本質(zhì)是什么窘行?
- 就是一個 while循環(huán),可以一直蓖疾郑活罐盔;
- 內(nèi)核態(tài) => 用戶態(tài); 用戶態(tài) 到 內(nèi)核態(tài)的切換救崔;
-
Runloop和線程是什么關(guān)系惶看?
struct __CFRunLoop { pthread_t _pthread; CFMutableSetRef _commonModes; CFMutableSetRef _commonModeItems; CFRunLoopModeRef _currentMode; CFMutableSetRef _modes; };
Runloop的底層數(shù)據(jù)結(jié)構(gòu)是什么樣的?有幾種 運行模式(mode)六孵?每個運行模式下面的 CFRunloopMode 是哪些纬黎?他們分別是什么職責(zé)?
- 運行模式:
- NSDefault
- UITracking
- UIInitialization
- GSEventReceive : 系統(tǒng)內(nèi)部的劫窒,我們用不到
- NSRunloopCommonModes
- Runloop 的監(jiān)聽狀態(tài)有哪幾種本今?
- Entry
- _objc_autoreleasePoolPush: -2147483647,優(yōu)先級最高
- berforeTimer
- beforeSouce
- beforeWaiting
- CoreAnimation::commit (setNeedsLayout/setNeedsDisplay)
- _objc_autoreleasePoolPop()
- _objc_autoreleasePoolPush()
- afterWaiting
- exit
- _objc_autoreleasePoolPop()
- Runloop 的工作流程大概是什么樣的烛亦?
https://juejin.cn/post/7068159603158024228
image.png
- Runloop 有哪些應(yīng)用诈泼?
- 創(chuàng)建一個保活線程去處理一個事件
[[NSThread alloc] initWithTarget:[self class] selector:@selector(startLoop) object:nil];
+ (void)startLoop {
@autoreleasepool {
// 創(chuàng)建context
CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &context);
// 創(chuàng)建source
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
CFRelease(source);
while (kCFRunLoopRunStopped != CFRunLoopRunInMode(
kCFRunLoopDefaultMode, ((NSDate *)[NSDate distantFuture]).timeIntervalSinceReferenceDate, NO)) {
NSLog(@"not reached assertion");
}
}
}
- 卡頓檢測
- (void)beginMonitor {
self.isMonitoring = YES;
//監(jiān)測 CPU 消耗
self.cpuMonitorTimer = [NSTimer scheduledTimerWithTimeInterval:3
target:self
selector:@selector(updateCPUInfo)
userInfo:nil
repeats:YES];
//監(jiān)測卡頓
if (runLoopObserver) {
return;
}
dispatchSemaphore = dispatch_semaphore_create(0); //Dispatch Semaphore保證同步
//創(chuàng)建一個觀察者
CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
runLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopAllActivities,
YES,
0,
&runLoopObserverCallBack,
&context);
//將觀察者添加到主線程runloop的common模式下的觀察中
CFRunLoopAddObserver(CFRunLoopGetMain(), runLoopObserver, kCFRunLoopCommonModes);
//創(chuàng)建子線程監(jiān)控
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//子線程開啟一個持續(xù)的loop用來進(jìn)行監(jiān)控
while (YES) {
// 88 毫秒的一個超時
long semaphoreWait = dispatch_semaphore_wait(dispatchSemaphore, dispatch_time(DISPATCH_TIME_NOW, STUCKMONITORRATE * NSEC_PER_MSEC));
if (semaphoreWait != 0) {
if (!runLoopObserver) {
timeoutCount = 0;
dispatchSemaphore = 0;
runLoopActivity = 0;
return;
}
//兩個runloop的狀態(tài)煤禽,BeforeSources和AfterWaiting這兩個狀態(tài)區(qū)間時間能夠檢測到是否卡頓
if (runLoopActivity == kCFRunLoopBeforeSources || runLoopActivity == kCFRunLoopAfterWaiting) {
//出現(xiàn)三次出結(jié)果
if (++timeoutCount < 3) {
continue;
}
// NSLog(@"monitor trigger");
// 打印堆棧
} //end activity
}// end semaphore wait
timeoutCount = 0;
}// end while
});
}
2. Runtime
2.1. 數(shù)據(jù)結(jié)構(gòu)
// 對象結(jié)構(gòu)體
struct objc_object {
Class _Nonnull isa; OBJC_ISA_AVAILABILITY;
};
// 實現(xiàn)了 objc_object 聲明方法
struct objc_class : objc_object {
// Class ISA; // 8字節(jié)
Class superclass; // 8字節(jié)
cache_t cache; // 16字節(jié)
class_data_bits_t bits; // objc_class的基地址
}
// bucket => [sel => imp]
struct cache_t {
explicit_atomic<uintptr_t> _bucketsAndMaybeMask; // 8字節(jié)
union { // 8字節(jié)
struct {
explicit_atomic<mask_t> _maybeMask; //4字節(jié)
uint16_t _occupied;// 4字節(jié)
};
explicit_atomic<preopt_cache_t *> _originalPreoptCache;
};
}
struct class_data_bits_t {
uintptr_t bits; // 8字節(jié)
}
// 精簡過的isa_t共用體
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
#if SUPPORT_PACKED_ISA
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1; // 引用計數(shù)表
uintptr_t extra_rc : 19; // 引用計數(shù)
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
};
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 8;
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
};
# else
# error unknown architecture for packed isa
# endif
#endif
image.png
字節(jié)對齊: 16字節(jié)對齊
- malloc_size: 分配內(nèi)存 16字節(jié)對齊
- class_getInstanceSize: 真實的大小
NSObject * obj = [[NSObject alloc]init];
NSLog(@"obj = %d,%d,%d",sizeof(obj),class_getInstanceSize([NSObject class]),malloc_size((__bridge const void *)(obj))); //8,8,16
super關(guān)鍵字
struct objc_super {
id object;
id superClass;
};
// objc_msgSendSuper( objc_super的結(jié)構(gòu)體, sel_registerName("test") )
[super test]
2.2 方法調(diào)用
- 先找isa指針
- 再找superClass
下面這種圖非常經(jīng)典
[obj iskindof:Class]
[obj isMemberof: Class]
方法調(diào)用
image.png