iOS App 启动优化

简介: 作为程序猿来说,“性能优化”是我们都很熟悉的词,也是我们需要不断努⼒以及持续进⾏的事情;其实优化是⼀个很⼤的课题,因为细分来说的话有⼤⼤⼩⼩⼗⼏种优化⽅向 ,但是切忌在实际开发过程中不能盲⽬的 为了优化⽽优化,这样有时可能会造成适得其反的负效果,需要我们根据实际场景以及业务需求进⾏合理优 化。接下来进⼊正题,本⽂将会以iOS App的启动优化为展开点进⾏探讨。

前言

作为程序猿来说,“性能优化”是我们都很熟悉的词,也是我们需要不断努⼒以及持续进⾏的事情;其实优化是⼀个很⼤的课题,因为细分来说的话有⼤⼤⼩⼩⼗⼏种优化⽅向 ,但是切忌在实际开发过程中不能盲⽬的 为了优化⽽优化,这样有时可能会造成适得其反的负效果,需要我们根据实际场景以及业务需求进⾏合理优 化。接下来进⼊正题,本⽂将会以iOS App的启动优化为展开点进⾏探讨。

启动流程:

iOS App 的启动我们都知道分为  为pre-main 和  main() 两个阶段,并且在这两个阶段中,系统会进 ⾏⼀系列的加载操作,过程如下:

1、pre-main阶段

1.  加载应⽤的可执⾏⽂件

2.  加载dyld动态连接器

3.  dyld递归加载应⽤所有依赖的动态链接库dylib

2、main()阶段

1.  dyld调⽤  main()

2.  调⽤UIApplicationMain()

3.  调⽤applicationWillFinishLaunching

4.  调⽤didFinishLaunchingWithOptions

阶段优化项

1、pre-main阶段

针对  pre-main 阶段做优化时,我们需要先详细了解其加载过程,这个可以在2016年WWDC 的  Optimizing App Startup Time 中详细了解到,   相关材料

1.1 Load dylibs

1.jpg

这⼀阶段dyld会分析应⽤依赖的  dylib (xcode7以后.dylib已改为名.tbd),找到其  mach-o ⽂件,打开和读取这些⽂件并验证其有效性,接着会找到代码签名注册到内核,最后对  dylib 的每⼀个  segment 调⽤ mmap()。不过这⾥的  dylib ⼤部分都是系统库,不需要我们去做额外的优化。

优化结论:

1、尽量不使⽤内嵌的dylib,从⽽避免增加 `Load dylibs`开销

2、合并已有的dylib和使⽤静态库(static archives),减少dylib的使⽤个数

3、懒加载dylib,但是要注意dlopen()可能造成⼀些问题,且实际上懒加载做的⼯作会更多

1.2 Rebase/Bind

2.jpg

在dylib的加载过程中,系统为了安全考虑,引⼊了ASLR (Address Space Layout Randomization)技术和    代码签名。由于ASLR的存在,镜像(Image,包括可执⾏⽂件、  dylib和bundle)会在随机的地址上加载,和 之前指针指向的地址(preferred_address)会有⼀个偏差(slide), dyld需要修正这个偏差,来指向正确的 地址。   Rebase在前,   Bind在后,  Rebase做的是将镜像读⼊内存,修正镜像内部的指针,性能消耗主要在     IO。 Bind做的是查询符号表,设置指向镜像外部的指针,性能消耗主要在CPU计算。

优化结论:

在此过程中,我们需要注意的是尽量减少指针数量,⽐如:

1. 减少ObjC类(class)、⽅法(selector)、分类(category)的数量

2. 减少C++虚函数的的数量(创建虚函数表有开销)

3. 使⽤ Swift struct (内部做了优化,符号数量更少)

1.3 Objc setup

3.jpg

⼤部分ObjC初始化⼯作已经在Rebase/Bind阶段做完了,这⼀步dyld会注册所有声明过的ObjC类,将分类插 ⼊到类的⽅法列表⾥,再检查每个selector的唯⼀性。

在这⼀步倒没什么优化可做的,  Rebase/Bind阶段优化好了,这⼀步的耗时也会减少。

1.4 Initializers

4.jpg

在这⼀阶段,   dyld开始运⾏程序的初始化函数,调⽤每个Objc类和分类的+load⽅法,调⽤C/C++ 中的构造器 函数(⽤attribute((constructor))修饰的函数),和创建⾮基本类型的C++静态全局变量。  Initializers阶段执⾏  完后,  dyld开始调⽤main()函数。

优化结论:

1. 少在类的+load⽅法⾥做事情,尽量把这些事情推迟到+initiailize

2. 减少构造器函数个数,在构造器函数⾥少做些事情

3. 减少构造器函数个数,在构造器函数⾥少做些事情

2、main()阶段

在这⼀阶段⾥,主要优化重点放在 SDK初始化、业务⼯具注册、整体

didFinishLaunchingWithOptions ⽅法中,因为我们的⼀些第三⽅    app ⻛格配置、启动引导⻚显示状态逻辑、版本更新逻辑等等基本⽅都会在这⾥进⾏,如果这部分逻辑没有做好优化梳理,随着业务不断拓展,臃肿的业务逻辑会直接导致启动时 间加⻓。

在满⾜业务需求的前提下,尽量减少  didFinishLaunchingWithOptions ⽅法在主线程中的事件处理逻辑, ⽐如:

1. 根据实际业务状况,梳理各个⼆⽅/三⽅库,找到可以延迟加载的库,做延迟加载处理,⽐如放到⾸⻚控制器 的viewDidAppear⽅法⾥。

2. 梳理业务逻辑,把可以延迟执⾏的逻辑,做延迟执⾏处理。⽐如检查新版本、注册推送通知等逻辑

3. 避免进⾏⼀些复杂/多余的计算逻辑,这类逻辑尽量进⾏异步延迟处理

4. 避免在⾸⻚控制器的viewDidLoad和viewWillAppear做太多容易阻塞主线程的事情,这2个⽅法执⾏完, ⾸⻚控制器才能显示

场景补充:

另外,在我们实际开发过程中,很多项⽬的⾸⻚控制器都会有⼀些后台可配、较为丰富的结构或者推荐数据  进⾏展示,⽽且我们的⾸⻚展示速度通常也会被纳⼊启动优化的⼀部分,其实对于这种类型的优化,如果我  们还只是⽤传统的  api -> data -> UI ⽅式进⾏的话,就很难有明显的改善空间,因为⽤户的⽹络状态 并不是可控项,如果不做其他处理的话,那在很多场景下对⽤户来说,即使我们放上⼀些占位图,展示的样式也是很不友好的,毕竟⾸⻚控制器对⽤户的第⼀视觉冲击影响还是⽐较⼤的。

对于这种场景下的优化来说,⼀般我们可以采取  Local + Network + Update 的⽅式在⼀定程度上优化 ⾸⻚加载速度:    即:

1、 app更新过程中,⾸先进⾏本地内嵌处理逻辑,内嵌⾸⻚数据结构( localDataBase)、内嵌⾸⻚样式所需 资源( localStorage)

2、在安装启动之后,对本地与线上数据更新记录进⾏对⽐,检测是否需要更新本地内嵌数据结构

3、检测到有需要更新的数据时,才会对指定结构进⾏静默更新,并且同步更新本地数据结构

这样做的好处是:

1、⾸⻚数据直接从本地加载,减少⽹络数据等待时间

2、仅检测数据key值变化,⼩数据量对⽐定向更新结构,减少api数据交互频次及数据包体积

3、能够保证⾸⻚对于⽤户来说会⼀直处于⼀个友好的展示状态

当然这种也并不是唯⼀的应对⽅式,⽽且也并⾮对所有场景都适⽤,只是提供⼀种思路⽽已,还是需要根据 项⽬的实际场景选择适合的优化⽅案。

统计时⻓

另外如果在开发过程中,我们想直观的查看  app 启动期间,各阶段的耗时情况,也可以在Xcode,的  edit scheme 设置添加   DYLD_PRINT_STATISTICS 为1 ,打印启动时⻓,例如

5.jpg

优化前启动时⻓:

6.jpg

优化后启动时⻓:

7.jpg

当然,这些log我们仅仅只能在开发调试阶段查看打印,那么在实际项⽬中,我们需要对线上项⽬的启动数据 进⾏监控,以便及时的定位和优化那些影响  app 启动时⻓的环节,这时我们应该怎样更好的处理呢?

当然我们可以通过服务器埋点上报的⽅式⾃⾏统计分析,不过这样⼀来会发现我们的统计成本就会⼤⼤增      加,⽽且结果分析也会变得不那么灵活。所以这⾥推荐⼀种简单的监控⽅式,那就是友盟的  U-APM 应能性 能监控SDK ,只需要我们进⾏简单的pod集成之后,便可根据我们的实际需要进⾏⼿动或者⾃动监控启动数  据,详情可以参考 U-APM, 并且为了⽅便我们对数据进⾏分析,友盟后台已经根据这些数据帮我们绘制出 了对应的分布图,我们可以⼀⽬了然的得出启动耗时分布、启动类型占⽐等等,如图:

8.jpg

哦.jpg

9.jpg

哦1.jpg

除此之外,我们还可以通过SDK进⾏崩溃分析、  ANR分析、监控告警、卡顿分析、内存分析等等诸多功能, 有了  U-APM 这个监控平台,其实在实际开发过程中很⼤程度的提升了我们对线上  app 的优化分析效率。

当然本⽂的介绍也只是⽐较浅显的优化项,仅供参考以及思路引导,优化之路任重⽽道远,还需要我们不断 的去探索、发现、提⾼。不过最后还是要提醒⼀句:在实际项⽬开发过程中,不要为了优化⽽优化,要根据 项⽬情况有针对性的进⾏优化。

参考:

探秘 Mach-O ⽂件

iOS底层 - 从头梳理 dyld 加载流程

iOSapp启动 - dyld加载App流程

wwdc2016optimizingappstartuptime.pdf

作者:武玉宝

原文链接
本文为阿里云原创内容,未经允许不得转载。 

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

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

相关文章

apache1.3 php编译,安装Apache1.3.29 - Linux+Apache+Mysql+PHP典型配置详解_Linux教程_Linux公社-Linux系统门户网站...

2.安装Apache1.3.29。我没有选择安装Apache2.0是我对他还是不放心,因为网上最新公布的apache的漏洞基本上是针对2.0,当然大家可以自己选择安装相应的版本。我这里讲的都是采用DSO动态编译的方法编译Apache.至于有关apache的编译方法,可以参考…

前后端、多语言、跨云部署,全链路追踪到底有多难?

简介: 完整的全链路追踪可以为业务带来三大核心价值:端到端问题诊断,系统间依赖梳理,自定义标记透传。 作者 | 涯海 全链路追踪的价值 链路追踪的价值在于“关联”,终端用户、后端应用、云端组件(数据库…

供应商太多,怎么才能高效比价?

本篇文章暨 CSDN《中国 101 计划》系列数字化转型场景之一。 《中国 101 计划——探索企业数字化发展新生态》为 CSDN 联合《新程序员》、GitCode.net 开源代码仓共同策划推出的系列活动,寻访一百零一个数字化转型场景,聚合呈现并开通评选通道&#xff0…

7张图揭晓RocketMQ存储设计的精髓

简介: RocketMQ 作为一款基于磁盘存储的中间件,具有无限积压能力,并提供高吞吐、低延迟的服务能力,其最核心的部分必然是它优雅的存储设计。 存储概述 RocketMQ 存储的文件主要包括 Commitlog 文件、ConsumeQueue 文件、Index 文…

庖丁解InnoDB之UNDO LOG

简介: Undo Log是InnoDB十分重要的组成部分,它的作用横贯InnoDB中两个最主要的部分,并发控制(Concurrency Control)和故障恢复(Crash Recovery),InnoDB中Undo Log的实现亦日志亦数据…

Ampere Altra Max 对比测试数据公布,性能能效双领先

在云计算领域,发展创新的脚步永不停歇。十多年前,伴随着虚拟化及高速网络的发展和成熟,云计算应运而生。在将工作负载迁移到云端的过程中,为了更好地适应云环境,软件架构得以重建,就如同搬进新家时&#xf…

钉钉宜搭入选Forrester《中国低代码平台市场分析报告》

简介: 🎉 最新:钉钉宜搭入选Forrester《中国低代码平台市场分析报告》! 11月12日,全球知名研究机构Forrester发布《中国低代码平台市场分析报告(The State Of Low-Code Platforms In China)》&…

被自己的行为蠢哭了,意识到原因后真香!

作者 | 零一来源 | 前端印象这两天在学习 node 相关的知识时,做出了一些错误的行为~在做用户登录相关业务时涉及到了 cookie、session 的存取,一搜就找到了 express-session 这个中间件,真香!配几个配置就可以自动生成 cookie、se…

一种命令行解析的新思路(Go 语言描述)

简介: 本文通过打破大家对命令行的固有印象,对命令行的概念解构后重新梳理,开发出一种功能强大但使用极为简单的命令行解析方法。这种方法支持任意多的子命令,支持可选和必选参数,对可选参数可提供默认值,支…

云原生 DevOps,模型化应用交付能力很重要

简介: DevOps 文化及其支撑其落地实践的自动化工具与平台能力在云原生架构渐为普及的背后,发挥了关键的价值。 撰稿:溪洋 云原生正在成为企业业务创新和解决规模化挑战的加速器。 云原生带来的变革绝不限于基础设施和应用架构等技术层面&a…

如何在 Kubernetes Pod 内进行网络抓包

作者 | Addo Zhang来源 | 云原生指北使用 Kubernetes 时,经常会遇到一些棘手的网络问题需要对 Pod 内的流量进行抓包分析。然而所使用的镜像一般不会带有 tcpdump 命令,过去常用的做法简单直接暴力:登录到节点所在节点,使用 root …

EDAS 4.0 助力企业一站式实现微服务架构转型与 K8s 容器化升级

简介: EDAS 正式来到 4.0 时代,发布多项重磅新能力;同时联合新产品—云原生应用设计开发平台 ADD 1.0,一起发布云原生应用研发&运维 PaaS 产品家族,助力企业应用架构现代化升级。 作者:安绍飞 前言 …

如何用20分钟就能获得同款企业级全链路灰度能力?

简介: MSE 微服务引擎将推出服务治理专业版,提供开箱即用且完整专业的微服务治理解决方案,帮助企业更好地实现微服务治理能力。如果您的系统也可以像本文描述的那样,快速具备完整的全链路灰度能力,并基于该能力进行进一…

云桌面场景化升级新作,锐捷网络发布全新远程办公“U空间”

编辑 | 宋慧 出品 | CSDN云计算 远程办公真的来了。 在硅谷的科技公司远程办公常态化之后,国内的科技大厂也在跟进中,如携程正式宣布的32混合办公模式。根据iiMedia Research艾媒咨询数据显示,在2020年新春期间,中国远程办公人员…

细说双 11 直播背后的压测保障技术

简介: 阿里云 PTS 站在双 11 巨人的肩膀上,是阿里全链路压测的延伸。PTS 通过伸缩弹性,轻松发起用户百万级别的流量,免去机器、人力成本;PTS 对流量的控制,能够实时脉冲,精准控制; 是…

【SpringCloud-Alibaba系列教程】14.一文教你入门RocketMQ

<本文已参与 RocketMQ Summit 优秀案例征文活动&#xff0c;点此了解详情> MQ简介 MQ(Message Queue)是一种跨进程的通信机制&#xff0c;用于消息传递。通俗点说&#xff0c;就是一个先进先出的数据结构。 MQ应用场景 异步解耦 很多场景不使用MQ会产生各个应用见紧密…

独家 | 2021双11背后的数据库硬核科技

简介&#xff1a; 今年双11&#xff0c;阿里云数据库技术有什么不一样&#xff1f; 2021年&#xff0c;是阿里巴巴首个100%云上双11 双11峰值计算成本 相比去年下降50% 作为全球规模最大的数字工程之一 双11无疑是对阿里技术人的“大考” 在又一次技术“严考"面前 …

前沿分享|阿里云资深技术专家 魏闯先:AnalyticDB PostgreSQL年度新版本发布

简介&#xff1a; 本篇内容为2021云栖大会-云原生数据仓库AnalyticDB技术与实践峰会分论坛中&#xff0c;阿里云资深技术专家 魏闯先关于“AnalyticDB PostgreSQL年度新版本发布”的分享。 本篇内容将通过三个部分来介绍AnalyticDB PG年度新版本发布。 一、AnalyticDB PG云原生…

Apache RocketMQ在我司的最佳实践--智慧政务场景下的分布式消息与分布式事务

<本文已参与 RocketMQ Summit 优秀案例征文活动&#xff0c;点此了解详情> 缘起 对于Apache RocketMQ的了解&#xff0c;追溯起来&#xff0c;可以说是从开源初始&#xff0c;就认识到了它。那时候的它&#xff0c;还是个幼年&#xff0c;没有成熟的社区&#xff0c;也…

前沿分享|阿里云数据库资深技术专家 姚奕玮:AnalyticDB MySQL离在线一体化技术揭秘

简介&#xff1a; 本篇内容为2021云栖大会-云原生数据仓库AnalyticDB技术与实践峰会分论坛中&#xff0c;阿里云数据库资深技术专家 姚奕玮关于“AnalyticDB MySQL离在线一体化技术揭秘”的分享。 本篇内容将通过三个部分来介绍AnalyticDB MySQL离在线一体化技术。 一、传统大…