通过安装包重排布优化 Android 端启动性能

  • 时间:
  • 浏览:1
  • 来源:UU快3直播官网

synchronized (mCachedXmlBlocks) {

* Loads an XML parser for the specified file.

/**

}

if (id != 0) {

……

* @param type the type of resource (used for logging)

将会 active list 中 page 的数量远大于 inactive list,这么 active list 头部的页面会被移入 inactive list 中,从而维持另有五个 表的平衡。简单的说,通过文件重布局的目的,只是将启动阶段只能用到的文件在 APK 文件中排布在一齐,尽将会的利用 pagecache 机制,用合适的磁盘 IO 次数,读取尽将会多的启动阶段只能的文件,减少 IO 开销,从而达到提升启动性能的目的。

}

}

*/

final String file = value.string.toString();

布局前后,Apk 中实际的文件并这么本质改变,只能位置所处了变化。这么为那先 从前 的调整会有性能造成影响?你什儿 原理要追溯到 Linux 的文件系统机制。

通过上述落地方案,在线下以及什儿 线上灰度版本中完成初步实验后,我门都考虑工程化,常态化的进行这件事情。在工程化时候 ,先对度量流程进行了扩充,探索出了有三种较为简单的度量手段。

if (DEBUG_LOAD) {

}

throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("

echo 1 > /proc/sys/vm/drop_caches

4. 落地方案

Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);

+ ": " + name + " at " + file);

3. 原理

}

XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id, int assetCookie,

目前整体方案,已上线支付宝钱包 Android App,该单项,启动性能,在整体全量用户下有 5% 左右的优化效果,低端机上效果较明显,根据不同机型,能有10%左右的启动性能优化效果。

本文作者:瑞涵

通过你什儿 最好的方式 ,就实现了文件重排布的简单过程,当然在支付宝的构建流程中,较为复杂,上方还涉及到重打包,重签名等一系列流程。后续内容会提到。

这里有另有五个 小插曲,在刚结速英语 了了调整文件顺序时,我门都通过测量发现效果不须好。时候发现了原困,从前 我门都调整的文件列表,只是度量阶段发现,所有所处磁盘 IO 的文件,把我门都排布到一齐,错误的认为,怎么能让我我门都调整了,整体 IO 情况表就会改善。从前 忽略了“此消彼长”的问题报告 ,将会只调整那先 文件,这么从前 排布在那先 文件上方,利用预读机制进缓存 cache 的文件,将会在启动阶段用到,将会会所处新的磁盘 IO。正确的调整最好的方式 ,应该能精确按时间顺序统计启动阶段的所有文件,排布在一齐,从前 所处一定量 IO,就能详细读到 cache 中。

简单看下某一次实验主 Apk 中文件调整前后的效果如下,十几个 和配置相关的移到文件头部。

throws NotFoundException {

本节将主要记录通过对支付宝 Android Apk 文件的重新布局,来改善 IO 性能的过程。

* @return a parser for the specified XML file

第一列表示所处 IO 的位置,将会为 0,则表示所处了真实的磁盘 IO;将会为 1,则表示从pagecache 缓存中读取了内容。

本文来自云栖社区合作伙伴“安卓巴士Android开发者门户”,了解相关信息还还可否关注“安卓巴士Android开发者门户”。

+ Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);

if (name != null) {

}

final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;

理想的做法是释放距离下次访问时间最久的 page,怎么能让很明显,这是不现实的。基于 LRU改进的 Two-List 是 Linux 使用的策略。你什儿 回收策略非常之类业务开发领域,常见的图片加载的缓存策略。LRU 算法是取舍最近一次访问时间最靠前的 page,即干掉最近没被光顾过的 page。原始 LRU 算法所处的问题报告 是,什儿 文件只会被访问一次,怎么能让按照 LRU 的算法,即使那先 文件时候 再只是会被访问了,怎么能让将会它们是时候 被访问的,就不让被选中。

adb shell

本章节我门都将围绕《支付宝 App 构建优化解析》另启新系列,细分拆解客户端在“代码管理”、“证书管理”、“版本管理”、“构建打包”等维度的具体实现方案展开讨论,带领我门都进一步了解支付宝在 App 构建模块下的持续优化。

}

从前 的度量方案,具备较深的技术含量,在你什儿 方案中,只能对 Linux 底层文件系统只能熟悉和了解,怎么能让还需具备修改源码的能力,此方案是由什儿 资深专家指导下实现,短期内,团队暂时无法独立你什儿 方案。

为了让整体方案可控,我门都想到了直接在 Android 源码的资源加载流程中记录日志,怎么能让通过日志直接分析,从前 启动阶段文件加载一目了然,当然过低也很明显,无法通过判断文件读取是通过磁盘 IO 还是 pagecache 缓存。

干预资源加载记录,要不通过 hook 最好的方式 ,要不只是直接改 framework,刷个 ROM,考虑到工程化自动化测试的因素,采用了修改 framework 的最好的方式 ,方便后续有测试平台,直接使用特定手机跑脚本执行即可。

以 Android 7.0 版本为例,主要修改 drawable 相关流程和 xml 相关流程。什儿 版本将会做测试度量机型的化,修改最好的方式 之类。

try {

……

1. 前言

/**

Facebook 的工具链优化方案 Redex,对于 dex 的优化,从度量到回归测试,开源出了一整套补救方案,对于 zip 的重布局,希望未来能将此整套方案,做到尽将会的“开箱即用”,赋能公司内外更多的 App。

if ((id >>> 24) == 0x1) {

if (value.string == null) {

 ●  第二是被访问过的数据,有很合适率会被再次访问。

结合 Android 系统实际来看,上层 App 每次读取磁盘时,文件系统默认会按 16 * 4k block 去磁盘读取数据,并把数据倒进 pagecache 中。将会下次读取文件将会在 pagecache 中,则不让所处真实的磁盘 IO,只是直接从 pagecache中 读取,大大提升读的传输速率。有缓存详细都是回收,pagecache 的从前 重要工作是释放 page,从而释放内存空间。Cache 回收的任务是取舍合适的 page 释放,怎么能让将会 page 是 dirty 的,只能将 page 写回到磁盘中再释放。

final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;

if (TRACE_FOR_MISS_PRELOAD) {

Log.i("AlipayRes", "ResourceId: " + Integer.toHexString(id) + " ResourcePackage name: " + getResourcePackageName(id) + " Loading drawable: " + file);

7z a -tzip archive.zip source* ^list.txt

调整前

Resources.Theme theme) {

通过数据还还可否发现,Apk 中每项文件,实际上是所处了磁盘 IO,还还可否尝试将启动阶段, Apk 中所用到的文件排布到一齐,期望通过一定量的 IO,就将所有的文件详细读到。时候 的工作,只能通过解析 zip 包形状,将上述结果中,文件偏移量对应到详细的文件名。首先只能得到安装包中的文件排布情况表,还还可否通过之类 010 Editor 的工具得到,为了工程化的考虑,也还还可否参考 zip 格式定义通过脚本分析 zip 文件实现。

Two-List 策略维护了另有五个 list,active list 和 inactive list。在 active list 上的 page 被认为是 hot 的,只能释放。只能 inactive list 上的 page 还还可否被释放的。首次缓存的数据的 page 会被加入到 inactive list 中,将会在 inactive list 中的 page 将会再次被访问,就会移入 active list 中。另有五个 链表都使用了伪 LRU 算法维护,新的 page 从尾部加入,移除时从头部移除,就像队列一样。

Log.i("AlipayRes", "ResourceId: " + Integer.toHexString(id) + " ResourcePackage name: " + getResourcePackageName(id) + " Loading xml: " + file);

Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)

final String name = getResourceName(id);

@NonNull

if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null

return cachedXmlBlocks[i].newParser();

private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,

adb shell am force-stop com.eg.android.AlipayGphone

// Log only framework resources



&& cachedXmlBlockFiles[i].equals(file)) {



}

*

final int num = cachedXmlBlockFiles.length;



}

在得到另有五个 启动阶段的文件列表后,第二步工作,只是根据你什儿 文件列表,在构建打包阶段,在 Apk 中把这每项文件排布在一齐。这里只能修改 7z 压缩工具的源码。支付宝构建流程,为了提升压缩传输速率,减少包大小,使用 7z 工具进行最后压缩出 Apk 的过程。这里在简单阐述下,重排布的原困,无论是那种压缩工具,zip 中文件顺序是文件系统的默认顺序,即按照阿拉伯数字和字母顺序。将会想指定文件排在一齐,必然要打破你什儿 规则。

修改 7z 源码的过程,简单思路如下,扩展另有五个 命令行参数,我门都使用了上箭头'^'(表意性强,提前的意思),还还可否传入 list.txt,怎么能让 7z 执行输出文件流时候 ,按照 list 中的文件顺序,改变最后的输出顺序,从而达到重排布的目的。之类如下命令,只是将 source 目录中,所有文件压缩,怎么能让把 list 中指定文件排布在 zip 包的结速英语 了了位置。

}

}

怎么能让内核将读取的数据缓存到 cache 中,从前 后续的读请求就还还可否命中 cache 了。Page 还还可否只缓存另有五个 文件每项的内容,不只能把整个文件都缓存进来。对磁盘的数据进行缓存从而提高性能主只是基于另有五个 因素:

……

 ●  线下使用工具度量 IO 情况表,观察启动阶段磁盘 IO 数量否有 减少,量化另有五个 “cache miss 率”的概念。 ●  线下通过架构设计 的方案,通过脚本,多次模拟冷启动,取平均值测量,消除将会误差,观察趋势。

 ●  线上灰度在什儿 优化和代码之类情况表下,只通过调整 IO,比较另有五个 版本的启动时间变化。 在重布局方案实验阶段,使用一二有三种方案较多,后续工程化落地和常态化优化时,应采用三有三种方案。

支付宝 App 在 Android 平台上,将会一定量业务快速上线,Android 长尾机型等原困,造成启动阶段及每项核心链路上,性能体验不理想,进而影响用户的使用的感受。

从纯业务深度,还还可否通过优化 UI 布局,优化代码形状,优化 bundle 加载等最好的方式 ,对性能体验有所改善。作为工程技术团队,按照传统思维来看,似乎无法对性能优化做十几个 贡献。经过什儿 方案调研后,我门都尝试通过对编译产物的优化,干预构建流程,以提升 App 性能。

原文发布时间为:2018-11-29

5. 演进

当内核发起另有五个 读请求时(之类应用应用程序发起 read() 请求),首先会检查请求的数据否有 缓存到了 pagecache 中。将会有,这么直接从内存中读取,不只能访问磁盘,这被称为 cache命中(cache hit)。将会 cache 中这么请求的数据,即 cache 未命中(cache miss),就只能从磁盘中读取数据。

if (!getResourcePackageName(id).equalsIgnoreCase("android")) {

* @throws NotFoundException if the file could not be loaded

final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;

如下图所示,Linux 底层文件系统中 VFS 上次 App 应用应用程序之间,所处一层 pagecache,pagecache 由内存中的物理 page 组成,其内容对应磁盘上的 block。Pagecache 的大小是动态变化的,还还可否扩大,也还还可否在内存过低时缩小。Cache 缓存的存储设备被称为后备存储(backing store),另有五个 page 通常含晒 多个 block,那先 block 不一定是连续的。

在了解原理时候 ,就只能考虑为什么会用工程化的方案在支付宝 App 上落地,主要从以下另有五个 流程来设计方案并落地。

……

重布局的前提只能是精确的度量,定位到那先 还还可否调整,只能调整的文件。你什儿 过程只能足够的准确,怎么能让会原困重布局时候 的效果不佳。

度量的最终目的是要,统计到支付宝启动阶段,那先 文件加载了,怎么能让是所处真实的磁盘IO,还是命中了 pagecache 缓存。我门都提供了另有五个 度量工具,通过修改 kernel 源码,dump 出文件系统的 IO 行为,在特定的 Android ROM 上打个补丁,用来统计启动时刻文件行为。每项数据如下:

*/

for (int i = 0; i < num; i++) {

怎么能让通过解析结果和先前的统计结果对应分析,就能找到 zip 中那先 文件,在启动阶段被读到,为重布局提供数据支撑。

刷入 ROM,替换修改后 framework 后,冷启动支付宝,清楚缓存,通过日志过滤即可得到详细启动文件加载列表。

* @param assetCookie the asset cookie for the file

调整后



* @param id the resource identifier for the file

// First see if this block is in our cache.

drawable 修改

* Loads a drawable from XML or resources stream.

if (!getResourcePackageName(id).equalsIgnoreCase("android")) {

* @param file the path for the XML file to parse

 ●  工程化:

只是单点能力都基本具备单点能力都具备后,只能找到另有五个 能尽将会自动化的方案。具体流程图如下。

后续对于 ReApk (优化Apk)流程,还还可否扩展什儿 的构建构建产物优化方案。

数据中,第一列的数据表示所处 IO 行为的文件,第二列表示该文件中此偏移量对应的部架构设计 生了 IO 行为。

2. 背景

@NonNull String type)



按照只是计划将文件详细调整完毕后,就到了验证效果的环节。主要有以下几种验证最好的方式 和思路: