二进制重排数据收集
1.Xcode 可以监测到 main 函数之前耗时时间。 通过添加环境变量可以打印app的启动时间分析(Edit scheme - run- arguments - Environment Variables ) main 函数之前的开启时间 DYLD_PRINT_STATISTICS 设置为1 详细的开启时间 DYLD_PRINT_STATISTICS_DETAILS 400毫秒以内属于正常
dylib loading time: 动态库载入耗时;rebase/binding time: 重定位、重绑定;ObjC setup time: OC类注册(OC是一个动态语言,读取二进制的data内容,找到OC的相关的信息,注册OC类;OC的runtime需要维护一张映射表(sel 和 imp 的映射, 类与类名的全局表, 加载mach-O的时候,所有的类都需要加载到全局表中));initializer time: 执行load、构造函数耗时;
2.打开instrament 工具 点击System Trace 工具 。点击左上角的红色运行按钮,当应用程序显示第一个页面关闭。并在target 栏中搜索Main Thead 找到当前的应用。
3.Build seting -->Linking -->Wright Link Map File 设为yes。 到对应的路径下找到启动时函数调用的一个.text 文档。
二进制原理与分析
虚拟内存的概念: 为了解决内存不足与安全方面的问题,诞生了虚拟内存。每个应用程序都有4G大小的虚拟内存空间,当需要加载应用程序时,操作系统通过每个对应应用的文件偏移量,按需装载到内存中。为了提高效率以分页的形式装载到内存中(在iOS系统中 是 16K , Mac 中是 4K)。这样起到隔离每个应用程序的作用。 由于按需加载,当应用程序使用到某个模块就会加载对应的模块,这个时候系统会抱缺页中断,停止用户操作系统将缺失的叶加载到内存中,并且系统也可以通过计算不活跃的页惊醒覆盖。 当我们启动的时候会有大量的缺页中断,所以虽然一个缺页中短时间很短,用户基本无感知,但是成百上千的缺页中段将有视觉上的观感。二进制重拍的原理是解决不必要的缺页中断,通过进行方法重新排列减少缺页中断的数量。
Clang插桩
添加Clang插桩标记 搜索:Other C Flags 添加编译参数:-fsanitize-coverage=func,trace-pc-guard 运行报错添加对应的两个函数的对应实现,并自定义方法写入文件。
#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
typedef struct {
void * pc;
void * next;
} SYNode;
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
static uint64_t N;
if (start == stop || *start) return;
for (uint32_t *x = start; x < stop; x++)
*x = ++N;
}
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
void *PC = __builtin_return_address(0);
SYNode * node = malloc(sizeof(SYNode));
*node = (SYNode){PC,NULL};
OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSMutableArray<NSString *> * symbleNames = [NSMutableArray array];
while (YES) {
SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode,next));
if (node == NULL) {
break;
}
Dl_info info;
dladdr(node->pc, &info);
NSString * name = @(info.dli_sname);
BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString * symbolName = isObjc ? name : [@"_" stringByAppendingString:name];
[symbleNames addObject:symbolName];
}
NSEnumerator * em = [symbleNames reverseObjectEnumerator];
NSMutableArray * funcs = [NSMutableArray arrayWithCapacity:symbleNames.count];
NSString * name;
while (name = [em nextObject]) {
if (![funcs containsObject:name]) {
[funcs addObject:name];
}
}
[funcs removeObject:[NSString stringWithFormat:@"%s",__func__]];
NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"hank.order"];
NSData * file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:nil];
NSLog(@"%@",funcStr);
}
配置二进制重排order文件
在对应的路径下找到我们生产的order文件,并且拷贝到工程目录第一层文件夹下,不是引用到工程 。 在Link 下找到 order file 将路径填写进去。 这时从新启动项目通过上面的第一步方式查看order 重拍是否起效。 注意:
- 1.在拿到
order 文件后将对应的插桩配置清除。 - 2.无法监听到
framework 中的方法。只能监听到自己写的所有方法,函数。 - 3.注意冷热启动带来的测试影响。
渲染优化
- 1.cup和GPU
cpu主要是用来各种计算,解码,GPU主要是通过计算好的数据进行屏幕渲染,也就是屏幕上显示的所用东西,都是通过GPU渲染出来的。 渲染后,将其放到帧缓存区中,iOS 的帧缓存区是双缓冲机制,有前针缓存,后针缓存。 - 2.image的处理,对于【uiimage imagewithname:】方法起时有一步隐藏的炒作,就是对image二进制数据进行解码操作,然后在现实到屏幕上
- 3.离屏渲染
圆角的设计,可以使用coreGraphics绘制裁剪圆角。
卡顿监控
1.耗电相关的主要来源 cpu,网络,定位,渲染 断点续传 如果仅仅只使用定位可以使用系统的框架,CllocationManager 的快速定位。 requestLocation
启动加载优化
- 1.减少动态库,合并动态库
- 2.定期清理不必要的类,分类
- 3.减少c++虚函数的数量
- 4.swift尽量使用struct
- 5.initialize 和 dispatch_once 取代 +load
- 6.main函数后尽量做一些延时处理。按需加载
安装包瘦身
安装包主要由可执行文件,资源组成 1.资源质量处理 2.去除没有用到的资源:https://github.com/tinymind/LSUnusedResources 可执行文件的瘦身 1.编译器优化,开启strip Linked 2.对一些没有用过的类进行清理,https://www.jetbrains.com/objc/ 检测未使用的代码:菜单栏-code-InspectCode (收费) 推荐: 数据结构与算法: 「严蔚敏」《数据结构》 《大话数据结构与算法》 网络层 《http权威指南》《TCP/IP详解卷1:协议》 架构与设计模式
|