前言
最近 Compose
曾经正式公布了 1.0
版本,这阐明谷歌认为 Compose
曾经能够用于正式生产环境了
那么相比传统的 XML
,Compose
的性能到底怎么样呢?
本文次要从构建性能与运行时两个方面来剖析 Compose
的性能,数据次要来源于:Jetpack Compose — Before and after 与 Measuring Render Performance with Jetpack Compose , 想理解更多的同学能够间接点击查看
构建性能
Compose
构建性能次要以 tivi 为例来进行阐明 Tivi
是一个开源的电影 App
,本来基于Fragment
与XML
构建,同时还应用了 DataBinding
等应用了注解处理器的框架
起初迁徙到应用 Compose
构建UI
, 迁徙过程分为两步
- 第一步:迁徙到
Navigation
与Fragment
, 每个Fragment
的UI
则由Compose
构建 - 第二步:移除
Fragment
,齐全基于Compose
实现UI
上面咱们就对 Pre-Compose
,Fragments + Compose
,Entirely Compose
三个阶段的性能进行剖析比照
APK
体积
包体积是咱们常常关注的性能指标之一,咱们一起看下 3 个阶段的包体积比照
能够看出,Tivi
的 APK
大小缩减了 46%
,从 4.49MB
缩减到 2.39MB
,同时办法数也缩小了17%
值得注意的是,在刚开始在利用中采纳 Compose
时,有时您会发现 APK
大小反而变大了
这是因为迁徙没有实现,老的依赖没有实现移除,而新的依赖曾经增加了,导致 APK
体积变大
而在我的项目齐全迁徙到 Compose
后,APK
大小会缩小,并且优于原始指标。
代码行数
咱们晓得在比拟软件我的项目时,代码行数并不是一个特地有用的统计数据,但它的确提供了对事物如何变动的一个察看指标。
咱们应用 cloc 工具来计算代码行数
cloc . --exclude-dir=build,.idea,schemas
后果如下图所示:
能够看出,在迁徙到 Compose
后,毫无意外的,XML
代码行缩小了 76%
乏味的是 kotlin
代码同样缩小了,可能是因为咱们能够缩小很多模板代码,同时也能够移除之前写的一些 View Helper
代码
构建速度
随着我的项目的一直变大,构建速度是开发人员越来越关怀的一个指标。
在开始重构之前,咱们晓得,删除大量的注解处理器会有助于进步构建速度,但咱们不确定会有多少。
咱们运行以下命令 5 次,而后取平均值
./gradlew --profile --offline --rerun-tasks --max-workers=4 assembleDebug
后果如下
这里思考的是调试构建工夫,您在开发期间会更关注此工夫。
在迁徙到 Compose
前,Tivi
的均匀构建工夫为 108.71
秒。
在齐全迁徙到 Compose
后,均匀构建工夫缩短至 76.96
秒!构建工夫缩短了 29%
。
构建工夫能缩短这么多,当然不仅仅是 Compose
的功绩,在很大水平上受两个因素的影响:
- 一个是移除了应用注解处理器的
DataBinding
和Epoxy
- 另一个是
Hilt
在AGP 7.0
中的运行速度更快。
运行时性能
下面咱们介绍了 Compose
在构建时的性能,上面来看下 Compose
在运行时渲染的性能怎么样
剖析前的筹备
应用 Compose
时,可能有多种影响性能的指标
- 如果咱们齐全在
Compose
中构建UI
会怎么? - 如果咱们对简单视图应用
Compose
(例如用LazyColumn
替换RecyclerViews
), 但根布局依然增加在XML
中 - 如果咱们应用
Compose
替换页面中一个个元素,而不是整个页面,会怎么样? - 是否可调试和
R8
编译器对性能的影响有多大?
为了开始答复这些问题,咱们构建了一个简略的测试程序。
在第一个版本中,咱们增加了一个蕴含 50 个元素的列表(其中理论绘制了大概 12 个)。该列表包含一个单选按钮和一些随机文本。
为了测试各种选项的影响,咱们增加以下 4 种配置, 以下 4 种都是开启了 R8
同时敞开了debug
纯 Compose
- 一个
XML
中,只带有一个ComposeView
, 具体布局写在Compose
中 XML
中只蕴含一个RecyclerView
,然而RecyclerView
的每一项是一个ComposeView
- 纯
XML
同时为了测试 build type
对性能的影响,也增加了以下 3 种配置
- 纯
Compose
, 敞开R8
并关上debug
- 纯
Compose
, 敞开R8
并敞开debug
- 纯
XML
,敞开R8
并关上debug
如何定义性能?
Compose
运行时性能,咱们个别了解的就是页面启动到用户看到内容的工夫
因而上面几个机会对咱们比拟重要
Activity
启动工夫, 即onCreate
Activity
启动实现工夫,即onResume
Activity
渲染绘制实现工夫,即用户看到内容的工夫
onCreate
与 onResume
的机会很容易把握,重写零碎办法即可,但如何取得 Activity
齐全绘制的工夫呢?
咱们能够给页面根 View
增加一个 ViewTreeObserver
, 而后记录最初一次onDraw
调用的工夫
应用 Profile
查看下面说的过程,如下别离为应用 XML
渲染与应用 Compose
渲染的具体过程, 即从 OnCreate
到调用最初一次 onDraw
的过程
渲染性能剖析
晓得了如何定义性能,咱们就能够开始测试了
- 每次测试都在几台设施上运行,包含最近的旗舰、没有
Google Play
服务的设施和一些便宜手机。 - 每次测试在同一台手机上都会运行 10 次,因而咱们不仅能够获取首次渲染工夫,也能够获取二次渲染工夫
- 测试
Compose
版本为 1.0.0
咱们依据下面定义的配置,反复跑了屡次,失去了一些数据,感兴趣的同学能够间接查看所有数据
剖析后果如上图所示,咱们能够得出一些论断
R8
和是否可调试对Jetpack Compose
渲染工夫产生了显着影响。在每次试验中,禁用R8
和启用可调试性的构建所破费的工夫是没有它们的构建的两倍多。在咱们最慢的设施上,R8
将渲染速度放慢了半秒以上,而禁用debug
又使渲染速度放慢了半秒。XML
中只蕴含一个ComposeView
的渲染工夫,跟纯Compose
的耗时差不多RecyclerView
中蕴含多个ComposeView
是最慢的。这并不奇怪, 在XML
中应用ComposeView
是有老本的,所以页面中应用的ComposeView
越少越好。XML
在出现方面比Compose
更快。没有方法解决这个问题,在每种状况下,Compose
的渲染工夫比XML
长约 33%。- 第一次启动总是比后续启动破费更长的工夫来渲染。如果您查看残缺的数据,第一个页面的渲染工夫简直是后续的两倍。
比拟让我诧异的是, 只管 Compose
没有了将 XML
转化成 View
的IO
操作,测量过程也因为固有个性测量进步了测量效率,但性能依然比 XML
要差
不过, 依据 Leland Richardson
的说法,当从 Google Play
装置应用程序时,因为捆绑的 AOT
编译,Compose
在启动时渲染会更快,从而进一步放大了与 XML
的差距
总结
通过上面对 Compose
性能方面的剖析,总结如下
- 如果齐全迁徙到
Compose
,在包体积,代码行数,编译速度等方面应该会有比拟大的改善 - 如果处于迁徙中的阶段,可能因为旧的依赖没有去除,而曾经引入了新的依赖,反而导致包体积等变大
- 只管没有了
XML
转换的IO
操作,测量过程也通过固有个性测量进行了优化,Compose
的渲染性能比起XML
依然有肯定差距 - 只管目前
Compose
在性能方面略有欠缺 (在大多数设施上仅超过一两帧),但因为其在开发人员生产力、代码重用和申明式UI
的弱小个性等方面的劣势,Compose
仍被举荐应用
视频:Android 开发中高级进阶:JetPack Compse 开发利用实战
原文:https://juejin.cn/post/7008522702835154980