iOS App冷启动优化:二进制重排

原理

         二进制文件中方法的加载顺序, 取决于方法在代码文件中的书写顺序,而不是调用顺序。 应用程序启动时会调用到的方法是有限的,但可能分散在很多个。 由于内存是分页管理的,要加载就要 整页加载 这就导致很多完全还用不到的方法,会在应用启动时就会被加载到内存,这需要开辟大量内存页,进而增加大量启动耗时。

        如果将BeforeMain阶段用到的方法都找出来出来,让他们在同一或相近的内存页中顺序提前加载,就可以大大减少应用启动时缺页异常出现的概率。

技术要点

     1)枚举出应用启动时会调用到的方法,将其保存到.order文件中

        可行的方案是Clang插

        

        首先,我们项目的Build Settings中搜索并设置 Other C Flags/ Other C++ Flags 为 -fsanitize-coverage=func,trace-pc-guard如果有swift代码,需要设置 Other Swift Flags 设置为 **** -sanitize-coverage=func -sanitize=undefined, 这样应用启动时所有方法都的边缘都被插入了__sanitizer_cov_trace_pc_guard(...)方法的调用

        然后, 我们需要实现__sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop)方法 然后使用dladdr()方法 可以调用的方法信息枚举出来,然后将其写入.order文件中即可 。                

//原子队列
static  OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {void *pc;void *next;
}SYNode;- (void)viewDidLoad {[super viewDidLoad];[self genrateOrderFile];
}
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {static uint64_t N;  // Counter for the guards.if (start == stop || *start) return;  // Initialize only once.printf("INIT: %p %p\n", start, stop);for (uint32_t *x = start; x < stop; x++)*x = ++N;  // Guards should start from 1.
}
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));
}
// 解析队列并生成.order文件
- (void) genrateOrderFile{NSMutableArray <NSString *> * symbolNames = [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];[symbolNames addObject:symbolName];}//取反NSEnumerator * enumerator = [symbolNames reverseObjectEnumerator];//去重NSMutableArray<NSString *> *funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];NSString * name;while (name = [enumerator nextObject]) {if (![funcs containsObject:name]) {[funcs addObject:name];}}[funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];//写入.order文件NSString * funcStr = [funcs  componentsJoinedByString:@"\n"];NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"demo.order"];NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];NSLog(@"%@",funcStr);
}
@end

        (2)设置应用在链接时, 根据.order文件顺序加载其中的符号

          只需在项目的Build Settings中搜索“Order File”,配置.order文件即可   

         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498003.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 刷题 [C++] 第148题.排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 题目分析 根据题意&#xff0c;可以使用归并排序来对链表进行排序。归并排序是基于分治的思想&#xff0c;比较容易实现的就是自顶向下的递归方式来实现。 先找出链表的中点&#x…

自学Python笔记总结(2——了解)

网络了解 网络调试助手 NetAssist.exe NetAssist.exe 使用方法请自行寻找 UDP协议 &#xff08;只能一来一回的的发消息&#xff0c;不可连续发送&#xff09; UDP 是User Datagram Protocol的简称&#xff0c; 中文名是用户数据报协议。在通信开始之前&#xff0c;不需要建…

如何利用graylog进行容器化日志管理?

Docker日志 当一个容器启动的时候&#xff0c;它其实是docker deamon的一个子进程&#xff0c;docker daemon可以拿到容器里面进程的标准输出&#xff0c;然后通过自身的LogDriver模块来处理&#xff0c;LogDriver支持的方式很多&#xff0c;默认写到本地文件&#xff0c;也可…

JAVA泛型浅析

Java范型generics&#xff0c;是JDK1.5引入的新特性&#xff0c;是一种编译时类型安全检测机制&#xff0c;可以在编译时检测到非法的类型。范型的本质是将类型参数化&#xff0c;将类型指定成一个参数。java中的集合就有使用&#xff0c;并且对外提供的三方库和SDK中使用也极为…

顶会ICLR2024论文Time-LLM:基于大语言模型的时间序列预测

文青松 松鼠AI首席科学家、AI研究院负责人 美国佐治亚理工学院(Georgia Tech)电子与计算机工程博士&#xff0c;人工智能、决策智能和信号处理方向专家&#xff0c;在松鼠AI、阿里、Marvell等公司超10年的技术和管理经验&#xff0c;近100篇文章发表在人工智能相关的顶会与顶刊…

手撕Java集合之简易版Deque(LinkedList)

在目前&#xff0c;许多互联网公司的面试已经要求能手撕集合源码&#xff0c;集合源码本身算是源码里比较简单的一部分&#xff0c;但是要在面试极短的10来分钟内快速写出一个简易版的源码还是比较麻烦的&#xff0c;很容易出现各种小问题。所以在平时就要注重这方面的联系。 以…

React入门之React_渲染基础用法和class实例写法

渲染元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>04元素渲染</title><script src&…

深度测试:指定DoC ID对ES写入性能的影响

在[[使用python批量写入ES索引数据]]中已经介绍了如何批量写入ES数据。基于该流程实际测试一下指定文档ID对ES性能的影响有多大。 一句话版 指定ID比不指定ID的性能下降了63%&#xff0c;且加剧趋势。 以下是测评验证的细节。 百万数据量 索引默认使用1分片和1副本。 指定…

如何在aws服务器上部署mysql

在AWS服务器上部署 MySQL 数据库可以通过以下步骤完成&#xff1a; 启动 EC2 实例&#xff1a; 在 AWS 控制台中启动一个 EC2 实例&#xff0c;选择适合你需求的实例类型和配置。 安全组配置&#xff1a; 确保你的 EC2 实例的安全组配置允许来自你的 IP 地址的 MySQL 连接。默…

浅谈下一代防火墙与Web应用防火墙的区别

如今&#xff0c;Web应用程序变得越来越复杂&#xff0c;更是黑客非常感兴趣的目标。在谈到网络安全的话题时&#xff0c;我们总会讨论下一代防火墙与Web应用防火墙的区别。当已经拥有下一代防火墙&#xff08;NGFW&#xff09;时&#xff0c;为什么需要Web应用程序防火墙&…

基于springboot实现旅游路线规划系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现旅游路线规划系统演示 摘要 随着互联网的飞速发展以及旅游产业的逐渐升温&#xff0c;越来越多人通过互联网获取更多的旅游信息&#xff0c;包括参考旅游文纪等内容。通过参考旅游博主推荐的旅游景点和规划线路&#xff0c;参考计划着自己的旅行&#xff0c…

自然语言处理(NLP)中NER如何从JSON数据中提取实体词的有效信息

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…