https://www.v2ex.com/t/259024#reply18
这个帖子是具体的内容,直接交互的 2 个方法并不能统计到子的方法运行时间,只能统计到父的
评论中有这么一句回复: 我建議你啓動時掃描所有 classes 然後找到目標做 is-a swizzle ,做一個 wrapper wrap 住所有要統計的 class ,控制住所有消息發送。但是就是肯定會影響性能。
请教一下这个具体的实现是怎么样的呢?
1
kitalphaj 2017-02-08 18:00:58 +08:00
他的意思应该是说你在启动的时候,扫描所有 classe (`objc_getClassList ` ), 然后每个 class 都看看是不是 view controller 的子类,如果是的话就把它的 viewDidLoad 换成带时间统计的 my_viewDidLoad 。(而不仅仅是换 UIViewController 这个具体类的 viewDidLoad 方法)。
|
2
Python666666 OP void -[_priv_NBSUIHookMatrix nbs_jump_viewDidLoad:superClass:](void * self, void * _cmd, void * * arg2, void * arg3) {
rbx = arg3; var_60 = arg2; r15 = _cmd; r14 = self; rax = [self class]; rax = class_getSuperclass(rax); if ((rbx != 0x0) && (rax != rbx)) { rax = var_60; if (rax != 0x0) { rdi = r14; (rax)(rdi, @selector(viewDidLoad)); } else { NSLog(@""); [[r14 super] viewDidLoad]; } } else { var_58 = r15; var_A8 = _currentViewController; r13 = *_currentViewController; if (r13 == 0x0) { rax = [_priv_NBSLensControllerReplacer alloc]; rax = [rax init]; rdi = *_currentViewController; *_currentViewController = rax; [rdi release]; r13 = *_currentViewController; } rbx = [[NSString stringWithFormat:@"%@", [r14 class]] retain]; rdi = r13; r13 = r14; [rdi setControllerName:rbx]; rdi = rbx; rbx = 0x0; [rdi release]; [*_currentViewController setVc_address:r13]; rdx = @"%d#loading"; rcx = r13; r12 = [[NSString stringWithFormat:rdx] retain]; if (r13 != 0x0) { rcx = class_getName([r13 class]); rbx = [[NSString stringWithFormat:@"MobileView/Controller/%s#%@", rcx, r8] retain]; } var_88 = rbx; r14 = [[_priv_NBSUILogCenter_assistant alloc] initWithControllerName:rbx, rcx, 0x0]; var_70 = r14; [r14 setVC_Address:_objc_release, rcx, 0x0]; [r14 setIsOther:0x0, rcx, 0x0]; [*_controllerStack push:r14, rcx, 0x0]; rbx = [_nbs_glb_all_activing_VCS() retain]; rcx = r12; var_90 = r12; [rbx setObject:r14 forKey:rcx, 0x0]; [rbx release]; rbx = [[NSDate date] retain]; [rbx timeIntervalSince1970]; xmm0 = intrinsic_mulsd(xmm0, *0x100086028); r12 = intrinsic_cvttsd2si(r12, xmm0); [rbx release]; [r14 setStartTime:r12, rcx, 0x0]; var_48 = _objc_release; r13 = [[NSString stringWithFormat:@"%s", class_getName([_objc_release class])] retain]; rbx = [NSStringFromSelector(var_58) retain]; r8 = *_currentViewController; rdx = r13; rcx = rbx; var_78 = [_nbs_embedIn_start() retain]; [rbx release]; [r13 release]; rbx = [[_priv_NBSLensInterfaceEventLogger shareObject] retain]; var_68 = rbx; r13 = [_priv_NBSLensUITraceSegment new]; var_50 = r13; rbx = [[rbx theStack] retain]; [rbx push:r13, rcx, r8]; [rbx release]; r14 = [[NSString stringWithFormat:@"%s", class_getName([_objc_release class])] retain]; r15 = [NSStringFromSelector(var_58) retain]; rbx = [[NSString stringWithFormat:@"%@#%@", r14, r15] retain]; var_98 = rbx; rdi = r15; [rdi release]; [r14 release]; [r13 setSegmentName:rbx]; rax = [NSDictionary dictionary]; rax = [rax retain]; var_A0 = rax; [r13 setSegmentParam:rax]; rbx = [[NSThread currentThread] retain]; rdx = rbx; [r13 setThreadInfomation:rdx]; [rbx release]; rbx = [[NSDate date] retain]; [rbx timeIntervalSince1970]; xmm0 = intrinsic_mulsd(xmm0, *0x100086028); var_58 = intrinsic_movsd(var_58, xmm0); [rbx release]; xmm0 = intrinsic_movsd(xmm0, var_58); [r13 setStartTime:rdx]; [r13 setEntryTime:0x0]; r12 = [_priv_NBSLensUITraceSegment new]; var_80 = r12; xmm0 = intrinsic_movsd(xmm0, var_58); [r12 setStartTime:0x0]; r14 = [[NSString stringWithFormat:@"%s", class_getName([var_48 class])] retain]; r13 = _objc_release; rbx = [[NSString stringWithFormat:@"%@#viewLoading", r14] retain]; [r12 setSegmentName:rbx]; [rbx release]; [r14 release]; rcx = var_30; rbx = [[NSDictionary dictionaryWithObjects:rbx forKeys:rcx count:0x0] retain]; [r12 setSegmentParam:rbx]; [rbx release]; rbx = [[NSThread currentThread] retain]; [r12 setThreadInfomation:rbx]; [rbx release]; [r12 setEntryTime:0x0]; rax = var_60; if (rax != 0x0) { rbx = var_48; (rax)(rbx, @selector(viewDidLoad), 0x0, rcx, 0x0); } else { rbx = var_48; NSLog(@""); [[rbx super] viewDidLoad]; } var_48 = rbx; _nbs_embedIn_finish(); rdx = [var_78 mach_tm2]; [var_70 setFinishTime:rdx]; rbx = [[NSDate date] retain]; [rbx timeIntervalSince1970]; xmm0 = intrinsic_mulsd(xmm0, *0x100086028); var_60 = intrinsic_movsd(var_60, xmm0); (r13)(rbx, @selector(timeIntervalSince1970), rdx); xmm0 = intrinsic_movsd(xmm0, var_60); xmm0 = intrinsic_subsd(xmm0, var_58); [var_50 setExitTime:intrinsic_cvttsd2si(rdx, xmm0)]; rbx = [[var_68 theStack] retain]; rdx = var_50; [rbx pop:rdx]; [rbx release]; rbx = [[var_68 theStack] retain]; r14 = [rbx isEmpty]; [rbx release]; if (r14 != 0x0) { rsi = @selector(childSegments); r14 = @selector(addObject:); } else { r14 = [[var_68 theStack] retain]; r15 = [[r14 peer] retain]; [r14 release]; [r15 startTime]; xmm1 = intrinsic_movsd(xmm1, var_58); xmm1 = intrinsic_subsd(xmm1, xmm0); rdx = intrinsic_cvttsd2si(rdx, xmm1); [var_50 setEntryTime:rdx]; [r15 startTime]; [var_50 setExitTime:intrinsic_cvttsd2si(rdx, intrinsic_subsd(intrinsic_movsd(xmm1, var_60), xmm0))]; r13 = [[r15 childSegments] retain]; r14 = @selector(addObject:); rdx = var_50; _objc_msgSend(r13, r14); [r13 release]; [r15 release]; rsi = @selector(childSegments); } rbx = [_objc_msgSend(var_80, rsi, rdx) retain]; _objc_msgSend(rbx, r14, var_50); [rbx release]; objc_setAssociatedObject(var_48, @"viewLoading", var_80, 0x1); rax = [*_controllerStack pop]; rax = [rax retain]; [rax release]; rbx = [[_priv_NBSLENS_VCSBuffer sharedObj] retain]; [rbx addObj:var_70]; [rbx release]; rbx = [_nbs_glb_all_activing_VCS() retain]; [rbx removeObjectForKey:var_90]; [rbx release]; [var_80 release]; [var_A0 release]; [var_98 release]; [var_50 release]; [var_68 release]; [var_78 release]; [var_70 release]; [var_88 release]; [var_90 release]; } return; } 这个是逆向的看别人实现的,但是看的不是很明白,有人一起来分析一下吗 |
3
Python666666 OP @kitalphaj objc_getClassList 这样的话,启动就扫描了所以的类实现了,好想也达不到这个效果, NSArray *sfl_classGetSubclasses(Class parentClass) {
int numClasses = objc_getClassList(NULL, 0); Class *classes = NULL; classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); numClasses = objc_getClassList(classes, numClasses); NSMutableArray *result = [NSMutableArray array]; for (NSInteger i = 0; i < numClasses; i++) { Class superClass = classes[i]; do { superClass = class_getSuperclass(superClass); } while(superClass && superClass != parentClass); if (superClass == nil) { continue; } [result addObject:classes[i]]; } free(classes); return result; } 类似这样吗 |
4
kitalphaj 2017-02-08 20:18:37 +08:00
@Python666666 为啥达不到,你相当于是把所有的实现都改了,那不就是所有时间都能统计了么。所以你到底想要实现什么?
|
5
xieweizhi007 2017-02-10 10:06:40 +08:00
@Python666666 , 就是 @kitalphaj 这么说做的
|