推广

iOS15系统启动时间加速

iseeyu3年前 (2024-02-21)推广151

iOS 15 中唯一的变化是数据现在由 linkedit_data_command 引用,该命令包含第一个节点的偏移量。为了验证这一点,我写了一个简短的 Swift App来解析 iOS 15 二进制文件并打印每个符号:

letbytes = (try!Data(contentsOf: url)asNSData).bytesbytes.processLoadComands { load_command, pointerinifload_command.cmd ==LC_DYLD_EXPORTS_TRIE{letdataCommand = pointer.load(as: linkedit_data_command.self)bytes.advanced(by:Int(dataCommand.dataoff)).readExportTrie()    }      }          extensionUnsafeRawPointer{funcreadExportTrie(){varfrontier = readNode(name:””)guard!frontier.isEmptyelse{return}      repeat{let(prefix, offset) = frontier.removeFirst()letchildren = advanced(by:Int(offset)).readNode(name:prefix)for(suffix, offset)inchildren {frontier.append((prefix+ suffix, offset))        }    }while!frontier.isEmpty    }          // Returns an array of child nodes and their offset    funcreadNode(name: String)-> [(String,UInt)] {guardload(as:UInt8.self) ==0else{// This is a terminal node    print(“symbol name \(name)”)return[]      }    letnumberOfBranches =UInt(advanced(by:1).load(as:UInt8.self))varmutablePointer =self.advanced(by:2)varresult = [(String,UInt)]()for_in0..

链

真正的变化在 LC_DYLD_CHAINED_FIXUPS。 在 iOS 15 之前的版本,变基、绑定和延迟绑定分别存储在单独的表中。现在它们已组合成链,在这个新的加载命令中,包含链起点的指针: 

App二进制文件被分解成多个段,每个段都包含一个可以绑定或变基的修复链(不再有延迟绑定)。二进制文件中的每个 64 位 rebase[3] 定位,对它指向的偏移量以及到下一个修正的偏移量进行编码,如以下结构所示:

structdyld_chained_ptr_64_rebase{uint64_ttarget :36,high8 :8,reserved :7,// 0snext :12,bind :1;// Always 0 for a rebase};

指针对象使用36位,足以容纳 2³ ⁶ = 64GB 的二进制文件,12 位用于提供下一个修正的偏移量(步幅 = 4)。因此,它可以指向 2 ¹² * 4 = 16kb范围内的任何位置——正是 iOS 上的页面大小。

这种非常紧凑的编码意味着遍历链的整个过程可以包含在二进制的现有大小内。 在我的测试中,超过 50% 的 dyld 数据对二进制大小的贡献被保存,因为只保留了少量元数据用来指示每个页面上的第一个修正。最终结果是Swift App的大小减少了 1mb 以上。

这个过程的源代码在 MachOLoaded.cpp 中 ,二进制设计在 /usr/include/macho-o/fixup-chains.h

排序问题

要理解这种改变背后的动机,我们必须注意App启动时开销最大的操作——缺页异常。在App启动期间访问文件系统上的代码时,需要通过缺页异常将其从文件写入到内存。App二进制文件中的每个 16kb区间都映射到内存中的一个页面。一旦页面被修改,它就需要在App运行期间一直保留在 RAM 中(称为脏页面)。iOS 通过压缩最近未使用的页面来优化这一点。

App启动时的修正需要更改App二进制文件中的地址,因此整个页面都被标记为脏页面。让我们看看在app启动期间修正程序使用了多少页面:

% xcrun dyldinfo -rebaseSnapchat.app/Snapchat> rebases% ruby -e ‘putsIO.read(“rebases”).split(“\n”).drop(2).map{ |a| a.split(” “)[2].to_i(16) /16384}.uniq.count’1554% xcrun dyldinfo -bindSnapchat.app/Snapchat> binds450

对于表的格式,首先解析变基,然后是绑定。这意味着变基需要许多缺页异常,并且最终主要是 IO 绑定 [4]。另一方面,绑定访问了30% 的变基使用的页面,有效地进行了第二次内存传递。

现在在 iOS 15版本中,链式修正将每个内存页面的所有更改组合在一起。dyld 现在可以通过一次遍历内存来更快地处理它们,同时完成变基和绑定。这使得诸如内存压缩器之类的操作系统功能能够利用众所周知的排序,而无需在绑定期间返回并解压缩旧页面。由于这些改变,dyld中的变基函数变成了一个空操作:

 https://opensource.apple.com/source/dyld/dyld-851.27/src/ImageLoaderMachOCompressed.cpp.auto.html

总的来说,这种改变主要影响对 iOS App进行逆向工程和探索动态链接器细节,这很好地提醒了大家,低级的内存管理会影响App性能。虽然这种改变仅在iOS 15版本上的App有效,但请记住,仍然可以做很多事情来优化App启动时间:

减少动态框架的数量

减少应用程序大小,从而减少内存页面的使用(这就是我制作 Emerge 的原因!)

将代码移出 +加载以及静态初始化程序

使用 更少的类

将工作推迟到绘制第一个框架后

参考链接:

[1] The symbol from dyldinfo is mangled, you can get the human readable name with xcrun swift-demangle ‘_$sSHMp’.

[2] Exports are the second piece of a bind. One binary binds to symbols exported from its dependencies.

[3] The same goes for binds, a pointer is actually a union of rebase and bind (dyld_chained_ptr_64_bind) with a single bit used to differentiate the two. Binds also require the imported symbol name which isn’t discussed here.

[4] https://asciiwwdc.com/2016/sessions/406

原文链接:https://medium.com/geekculture/how-ios-15-makes-your-app-launch-faster-51cf0aa6c520

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56777.html

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片