1. hook objc_msgsend

该方法直接使用汇编编写 hook_msgSend,然后利用 fishhook 进行 hook。原理也相对简单,fishhook 会遍历 image ,查找 image 中的 __la_symbol_ptr 和 __nl_symbol_ptr/__got 表,该过程一般发生在动态链接之后, main 函数运行之后。也可通过 +load 来进行 rebind,但是相对不可控。因此,直接 hook objc_msgsend 方法就可以知道 OC 方法的耗时,进而进行监控和针对性优化;

存在的问题:

  1. 分类 hook 不到?
  2. 只能全部 hook,不能部分 hook;
  3. hook 之后的计时方法本身也是一种消性能耗;

第二个问题会导致:

  1. 全部 hook 会有性能问题;
  2. 项目本身可能会 crash,bad_access,问题不一定好解决。一个 crash 无法解决,不能部分 hook,整个项目就不能用这个工具;

因此发展成第二种方式......

2. 静态插桩

静态插桩不知道这个叫法是怎么来的,感觉不应该是插桩。桩意味着 stub 桩函数,插桩可能是指修改 __TEXT段的 stub 函数吧。

而这里的实现方式是指修改符号表中 objc_msgsend 的指向,或者是修改字符串表的 objc_msgsend 为 hook_msgSend 。

对比静态插桩,在静态时期进行 hook 的方式还有:

  1. llvm 语法树解析,即将 objc_msgSend 解析成我们自己的函数,如果 hook_msgSend;
  2. 编译完成之后,链接之前,修改目标文件的 text 段调用;

上述两种办法都相对较难,门槛也比较高,而静态插桩的方式更简单有效:

因为链接之前,所有的文件都会被编译成目标文件。而目标文件中对外部函数的调用就会存在一张 symbol table。链接时,所有目标文件的 symbol table 会被整合到最终的可执行文件中,以此完成链接的操作。

这个方案的基本原理就是编译完成之后,链接之前,替换所有目标文件(.o 文件)的中的字符串表。因为 symbol table 中不存储字符串,存的是 symbol 相关的信息和指针,静态外部符号在静态链接之前为 0,动态外部符号在动态链接之前为 0。另外,hook string table 本身会更简单,替换了这个 string 之后,该目标文件的所有 objc_msgSend 方法都被改成了 hook_msgSend 方法了。

总结:

  1. 无法直接修改 symbol table 中的 string,或者说修改成本较大(遍历symbol table且在strtab中新增一个hook_msgSend且要hook objc_msgSend);
  2. 直接修改 string table 中的 objc_msgSend 可以完成整个目标文件的替换;
  3. 因为实在链接之前,所以整个目标文件的替换是相对于 .o 文件的,这样就可以支持部分文件的 hook;

3. 二进制重排

App 启动之前会加载 Mach-O 文件到内存中。虚拟内存和磁盘不一样的地方在于内存分页,Mach-O 中的 segment 被夹在进入内存时,会因为分页的原因导致其在内存中的大小和磁盘中的大小不一定一致。

App 在启动周期时会调用很多函数,因此会加载很多符号的实现,即 __TEXT 段的代码。也正是因为分页的问题,如果启动时加载的函数过于分散,那么在启动时就会进行很多次的 Page Fault。

加载 image 时是把所有的 Mach-O 文件加载进内存吗?感觉应该不是,dyld 源码上好像是会先加载一个 page,如果不够,再继续加载 page。估计是先分配固定虚拟内存,以保证地址的连续且符合 Mach-O ,此时未 Page In 的虚拟内存不指向具体的物理内存。调用的代码未加载时再触发 Page In;存疑~~

二进制重排的核心在于将启动时调用的符号尽量排序到一个 page 中,以此来最大程度减少 Page Fault 的次数,减少 I/O 次数,最终来优化启动时间;

二进制重排存在的问题:

  1. 难度较大;
  2. 效果待确认;
  3. iOS13 之后,dyld3 引入 closure,重排的性价比可能会很低;

dyld3 中,App 启动需要的信息被存入磁盘中,相当于原来需要在启动前做的工作提前做了这部分工作。具体原理未知,所以二进制重排的方案的效果有待验证。

4. 相关文章

静态插桩的方式来实现Hook Method

TimeProfiler

监控所有的OC方法耗时。

性能优化iOS

静态拦截iOS对象方法调用的简易实现

抖音品质建设 - iOS启动优化《原理篇》

抖音品质建设 - iOS启动优化《实战篇》

抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15%


http://www.taodudu.cc/news/show-1912761.html

相关文章:

  • iOS:segment对齐原则
  • HTTP缓存机制及其在iOS中的应用
  • iOS:SideTable
  • iOS:isa指针
  • iOS底层:PAGEZERO的作用
  • iOS图形学(三):屏幕成像原理
  • iOS图形学(四):iOS中的绘图框架
  • Java基础(一):简介和基础数据类型
  • Java基础(二):面向对象
  • Java:常量池
  • Java基础(三):常用对象
  • Java基础(四):异常处理
  • Java基础(五):多线程
  • Android:权限处理
  • AsyncTask的基本使用
  • 在Nginx中配置SSL证书
  • Base64编码流程
  • Nginx配置基础认证
  • Cookie、Session、Token、RefreshToken
  • JSCore浅析及其在iOS上的使用
  • 编程语言的动态性(Dart和OC对比)
  • iOS:Universal Link
  • AFN中的鉴权
  • openGL ES 教程(二):渲染管线
  • MySQL(2)----DDL语句之增、删、改、查操作
  • MySQL(3)-----DML数据库操作(上)
  • 线性表的基本运算
  • MySQL(4)-----DML数据库操作(下)
  • MySQL(1)----帮助使用
  • MySQL(6)-----数据类型

iOS:主流启动优化方案浅析相关推荐

  1. 启动优化·基础论·浅析 Android 启动优化

    " [小木箱成长营]启动优化系列文章(排期中): 启动优化 · 工具论 · 启动优化常见的六种工具 启动优化 · 方法论 · 这样做启动优化时长降低 70% 启动优化 · 实战论 · 手把手 ...

  2. iOS App 启动优化

    简介: 作为程序猿来说,"性能优化"是我们都很熟悉的词,也是我们需要不断努⼒以及持续进⾏的事情:其实优化是⼀个很⼤的课题,因为细分来说的话有⼤⼤⼩⼩⼗⼏种优化⽅向 ,但是切忌在实际 ...

  3. android 启动优化方案,Android 项目优化(五):应用启动优化

    介绍了前面的优化的方案后,这里我们在针对应用的启动优化做一下讲解和说明. 一.App启动概述 一个应用App的启动速度能够影响用户的首次体验,启动速度较慢(感官上)的应用可能导致用户再次开启App的意 ...

  4. 万字好文!几乎包含了市面上所有启动优化方案

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 关注订阅号「程序员小乐」,收看更多精彩内容 每日英文 Don't be af ...

  5. Android启动优化方案调研

    /   今日科技快讯   / 7月21日,国家互联网信息办公室依据<网络安全法><数据安全法><个人信息保护法><行政处罚法>等法律法规,对滴滴全球股份 ...

  6. iOS app的启动优化

    返回上级目录:iOS面试专题一 文章目录 1.冷启动分为两个阶段:main函数之前和之后 2.pre-main阶段 2.1 Load dylibs image:加载动态库 2.2 Rebase/Bin ...

  7. 马蜂窝 iOS App 启动治理:回归用户体验

    增长.活跃.留存是移动 App 的常见核心指标,直接反映一款 App 甚至一个互联网公司运行的健康程度和发展动能.启动流程的体验决定了用户的第一印象,在一定程度上影响了用户活跃度和留存率.因此,确保启 ...

  8. android启动优化解读

    性能优化包括很多方面,比如:启动优化.布局优化.内存优化.卡顿优化.网络优化.数据库优化.内存泄漏优化.包体积优化等等.我们想要进行性能优化就要了解基本的原理,这篇文章针对启动这一方面来谈一谈相关的原 ...

  9. Android性能优化系列:启动优化

    文章目录 1 应用启动类型 1.1 冷启动 1.2 温启动 1.3 热启动 2 查看启动耗时 2.1 adb命令查看 2.2 Logcat Displayed查看启动耗时 2.3 手动记录启动耗时 2 ...

  10. 你想要的Android性能优化系列:启动优化 !

    文章目录 一.概述 二.应用启动流程介绍 三.优化核心思想 四.时间检测 4.1 Displayed 4.2 adb shell 4.3 reportFullyDrawn() 4.4 代码打点 4.5 ...

最新文章

  1. 一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」
  2. 在虚拟中开启Windows 8.1的Hyper-V平台
  3. 推荐一个强大的Go库-rk-boot,未来 Go领域的SpringBoot?
  4. [HDU 4842]--过河(dp+状态压缩)
  5. android 讲程序设为默认主屏幕_轻松搞定 PC 副屏,双屏幕更方便!
  6. CCPC-EDG专场——E.Buy and Delete
  7. matlab gui期末设计,MATLABGUI课程设计期末大作业湖南理工学院
  8. 亲测ArcGis albers投影转换为经纬度的代码
  9. 2019-2020年目标跟踪论文汇总
  10. 扇形涂色问题(Python)
  11. 新一配:程序员在地铁上写代码被路人吐槽:有什么好装的!网友评论炸锅了
  12. 洛谷P1488 肥猫的游戏
  13. 如何让你自己做的网站他人可以访问——外网访问
  14. 在线预览 Word、Excel、PowerPoint 文档——Office Online插件使用
  15. unity 3d如何隐藏物体
  16. BUUCTF-社团考核
  17. [动态规划] 区间DP
  18. Inception v3 自学笔记
  19. MVC与MVVM区别
  20. android 动画后动画效果,Android5.0之后 VectorDrawable实现超炫酷动画效果

热门文章

  1. 小知识-Spring Boot是如何确定当前运行环境
  2. 对于区块链在现实落地的一些技术业务关注点
  3. PHP中的++和--
  4. Jni 返回jstring字符串
  5. JS 通过选择百度地图地址获取经纬度自动填充到文本框中的方法
  6. MyEclipse 中各种 libraries 的含义
  7. 程序包管理之编译安装
  8. Centos 6.4 安装erlangrabbitmq
  9. Installation openQRM
  10. 【笔记】mac os命令行编译objective-c