相比 XML , Compose 性能到底怎么样?

前言

最近Compose已经正式发布了1.0版本,这说明谷歌认为Compose已经可以用于正式生产环境了
那么相比传统的XML,Compose的性能到底怎么样呢?

本文主要从构建性能与运行时两个方面来分析Compose的性能,数据主要来源于:Jetpack Compose — Before and afterMeasuring Render Performance with Jetpack Compose , 想了解更多的同学可以直接点击查看

构建性能

Compose构建性能主要以 tivi 为例来进行说明
Tivi是一个开源的电影App,原本基于FragmentXML构建,同时还使用了DataBinding等使用了注解处理器的框架
后来迁移到使用Compose构建UI,迁移过程分为两步

  1. 第一步:迁移到NavigationFragment,每个FragmentUI则由Compose构建
  2. 第二步:移除Fragment,完全基于Compose实现UI

下面我们就对Pre-Compose,Fragments + Compose,Entirely Compose三个阶段的性能进行分析对比

APK体积

包体积是我们经常关注的性能指标之一,我们一起看下3个阶段的包体积对比


image.png

image.png

可以看出,TiviAPK 大小缩减了 46%,从 4.49MB 缩减到 2.39MB,同时方法数也减少了17%

值得注意的是,在刚开始在应用中采用Compose时,有时您会发现APK大小反而变大了
这是因为迁移没有完成,老的依赖没有完成移除,而新的依赖已经添加了,导致APK体积变大
而在项目完全迁移到Compose后,APK 大小会减少,并且优于原始指标。

代码行数

我们知道在比较软件项目时,代码行数并不是一个特别有用的统计数据,但它确实提供了对事物如何变化的一个观察指标。
我们使用cloc工具来计算代码行数

cloc . --exclude-dir=build,.idea,schemas

结果如下图所示:


image.png

可以看出,在迁移到Compose后,毫无意外的,XML代码行减少了76%
有趣的是kotlin代码同样减少了,可能是因为我们可以减少很多模板代码,同时也可以移除之前写的一些View Helper代码

构建速度

随着项目的不断变大,构建速度是开发人员越来越关心的一个指标。
在开始重构之前,我们知道,删除大量的注解处理器会有助于提高构建速度,但我们不确定会有多少。

我们运行以下命令5次,然后取平均值

./gradlew --profile --offline --rerun-tasks --max-workers=4 assembleDebug

结果如下


image.png

这里考虑的是调试构建时间,您在开发期间会更关注此时间。

在迁移到Compose前,Tivi 的平均构建时间为 108.71 秒。
在完全迁移到 Compose 后,平均构建时间缩短至 76.96 秒!构建时间缩短了 29%
构建时间能缩短这么多,当然不仅仅是Compose的功劳,在很大程度上受两个因素的影响:

  1. 一个是移除了使用注解处理器的DataBindingEpoxy
  2. 另一个是HiltAGP 7.0 中的运行速度更快。

运行时性能

上面我们介绍了Compose在构建时的性能,下面来看下Compose在运行时渲染的性能怎么样

分析前的准备

使用Compose时,可能有多种影响性能的指标

  • 如果我们完全在Compose中构建UI会怎样?
  • 如果我们对复杂视图使用Compose(例如用 LazyColumn 替换 RecyclerViews),但根布局仍然添加在XML
  • 如果我们使用Compose替换页面中一个个元素,而不是整个页面,会怎么样?
  • 是否可调试和R8编译器对性能的影响有多大?

为了开始回答这些问题,我们构建了一个简单的测试程序。
在第一个版本中,我们添加了一个包含50个元素的列表(其中实际绘制了大约 12 个)。该列表包括一个单选按钮和一些随机文本。

image.png

为了测试各种选项的影响,我们添加以下4种配置,以下4种都是开启了R8同时关闭了debug

  1. 纯Compose
  2. 一个XML中,只带有一个ComposeView,具体布局写在Compose
  3. XML中只包含一个RecyclerView,但是RecyclerView的每一项是一个ComposeView
  4. XML

同时为了测试build type对性能的影响,也添加了以下3种配置

  1. Compose,关闭R8并打开debug
  2. Compose,关闭R8并关闭debug
  3. XML,关闭R8并打开debug

如何定义性能?

Compose运行时性能,我们一般理解的就是页面启动到用户看到内容的时间
因此下面几个时机对我们比较重要

  1. Activity启动时间,即onCreate
  2. Activity启动完成时间,即onResume
  3. Activity渲染绘制完成时间,即用户看到内容的时间

onCreateonResume的时机很容易掌握,重写系统方法即可,但如何获得Activity完全绘制的时间呢?
我们可以给页面根View添加一个ViewTreeObserver,然后记录最后一次onDraw调用的时间

使用Profile查看上面说的过程,如下分别为使用XML渲染与使用Compose渲染的具体过程,即从OnCreate到调用最后一次onDraw的过程

image.png

image.png

渲染性能分析

知道了如何定义性能,我们就可以开始测试了

  1. 每次测试都在几台设备上运行,包括最近的旗舰、没有Google Play服务的设备和一些廉价手机。
  2. 每次测试在同一台手机上都会运行10次,因此我们不仅可以获取首次渲染时间,也可以获取二次渲染时间
  3. 测试Compose版本为1.0.0

我们根据上面定义的配置,重复跑了多次,得到了一些数据,感兴趣的同学可以直接查看所有数据

image.png

分析结果如上图所示,我们可以得出一些结论

  • R8和是否可调试对Jetpack Compose渲染时间产生了显着影响。在每次实验中,禁用R8和启用可调试性的构建所花费的时间是没有它们的构建的两倍多。在我们最慢的设备上,R8 将渲染速度加快了半秒以上,而禁用debug又使渲染速度加快了半秒。
  • XML中只包含一个ComposeView的渲染时间,跟纯Compose的耗时差不多
  • RecyclerView中包含多个ComposeView是最慢的。这并不奇怪,在XML中使用ComposeView是有成本的,所以页面中使用的ComposeView越少越好。
  • XML在呈现方面比Compose更快。没有办法解决这个问题,在每种情况下,Compose 的渲染时间比 XML 长约 33%。
  • 第一次启动总是比后续启动花费更长的时间来渲染。如果您查看完整的数据,第一个页面的渲染时间几乎是后续的两倍。

比较让我惊讶的是,尽管Compose没有了将XML转化成ViewIO操作,测量过程也因为固有特性测量提高了测量效率,但性能仍然比XML要差
不过,根据Leland Richardson说法,当从Google Play安装应用程序时,由于捆绑的AOT编译,Compose 在启动时渲染会更快,从而进一步缩小了与XML的差距

总结

经过上面对Compose性能方面的分析,总结如下

  1. 如果完全迁移到Compose,在包体积,代码行数,编译速度等方面应该会有比较大的改善
  2. 如果处于迁移中的阶段,可能因为旧的依赖没有去除,而已经引入了新的依赖,反而导致包体积等变大
  3. 尽管没有了XML转换的IO操作,测量过程也通过固有特性测量进行了优化,Compose的渲染性能比起XML仍然有一定差距
  4. 尽管目前Compose在性能方面略有欠缺(在大多数设备上仅超过一两帧),但由于其在开发人员生产力、代码重用和声明式UI的强大特性等方面的优势,Compose仍被推荐使用

视频:Android开发中高级进阶:JetPack Compse开发应用实战

原文: https://juejin.cn/post/7008522702835154980

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容