如何用AI技术降噪? QCon 广州“音视频架构实践”专场给你答案! 了解详情
写点什么

美团开源 Graver 框架:用“雕刻”诠释 iOS 端 UI 界面的高效渲染

  • 2020 年 2 月 25 日
  • 本文字数:4251 字

    阅读完需:约 14 分钟

美团开源Graver框架:用“雕刻”诠释iOS端UI界面的高效渲染

Graver 是一款高效的 UI 渲染框架,它以更低的资源消耗来构建十分流畅的 UI 界面。Graver 独创性的采用了基于绘制的视觉元素分解方式来构建界面,得益于此,该框架能让 UI 渲染过程变得更加简单、灵活。目前,该框架已经在美团 App 的外卖频道、独立外卖 App 核心业务场景的大多数业务中进行了应用,同时也得到美团外卖内部技术团队的认可和肯定。


App 渲染性能优化是一个普遍存在的问题,为了惠及更多的前端开发同学,美团外卖 iOS 开发团队将其进行开源,Github 项目地址与使用文档详见:https://github.com/Meituan-Dianping/Graver 。我们希望该框架能够应用到更广阔的业务场景。当然,我们也知道该框架尚有待完善之处,也希望能与更多技术同行一起交流、探讨、共建。


前言

我们为什么需要关注界面的渲染性能?App 使用体验主要包含产品功能、交互视觉、前端性能,而使用体验的好与坏,直接影响用户持续使用还是转而使用其他 App,所以我们非常关注 App 的渲染性能。而且在互联网产品流量竞争愈发激烈的大背景下,优质的使用体验可以为现有用户提供更好的服务,进而提高用户转化和留存,这也意味着创收、盈利。



图 1 使用体验与转化、留存


背景

美团外卖 App 从 2013 年成立至今,已经走过了五个春秋,在技术层面先后经历了快速验证、模块化、精细化和平台化四个阶段,产品形态上也日趋成熟。在此期间,我们构建并完善了监控、报警、容灾、备份等各项基础设施,Metrics 即是其中的性能监控系统。


曾经一段时间,我们以外卖 App 首页商家卡片列表为例,通过 Metrics 性能监控系统发现其在 FPS、CPU、Memory 等方面的各项指标并不理想。于是,通过 Xcode 自带的 TimeProfile 等性能检测工具,然后结合代码分析等手段找到了现存性能瓶颈。与此同时,我们梳理其近半年的迭代版本需求发现,UI 往往需要根据不同场景甚至不同用户展示不同的内容。为了不断迎合用户的需求,快速应对市场变化,这种特征还会持续存在。然而,它会带来以下问题:


  • 视图层级愈加复杂、视图数量愈加众多,从版本长期迭代来看是潜在的性能瓶颈点。

  • 如何快速、高效支撑 UI 变化,同时保证不会二次引入性能瓶颈。



图 2 影响渲染性能、研发效率的瓶颈点


Graver 介绍

为了解决现存的性能瓶颈以及后续潜在的性能瓶颈,我们期望构建一套解决方案,该方案能在充分满足外卖业务特征的前提下,以标准化、一站式的方式解决 iOS 端 App 的渲染性能问题,并且对研发效率有一定提升, Graver(雕工)框架应运而生。


因为 Graver 独创性地采用了全新的视觉元素分解思路,所以该框架使用起来十分灵活、简单。我们先来看一下 Graver 的主要特点:


性能表现优异


以外卖 App 首页商家列表为例,应用 Graver 之后 5 分位滚动帧率从满帧的 84% 提升至 96% ,50 分位几乎满帧;CPU 占用率下降了近 6 个百分点 ,有效提升了空闲 CPU 的资源利用率,降低了峰值 CPU 的占用率。如图 3 所示:



图 3 优化前后技术指标对比


“一站式”异步化


Graver 从文本计算、样式排版渲染、图片解码,再到绘制,实现了全程异步化,并且是线程安全的。使用 Graver 可以一站式获得全部性能优化点,可以让我们:


  • 不再担心散点式的“遇见一处改一处”的麻烦。

  • 不再担心离屏渲染等各种可能导致性能瓶颈的问题,以及令人头痛的解决办法。

  • 不再担心优化会有遗漏、优化不到位。

  • 不再担心未来变化可能带来的任何性能瓶颈。


性能消耗的“边际成本”几乎为零


Graver 渲染整个过程除画板视图外完全没有使用 UIKit 控件,最终产出的结果是一张位图(Bitmap),视图层级、数量大幅降低。以外卖 App 首页铂金展位视图为例,原有方案由 58 个控件、12 层级拼接而成;而应用 Graver 后仅需 1 个视图、1 级层级绘制而成。 伴随着需求迭代、视觉元素变化,性能消耗恒属常数级。如图 4 所示:



图 4 外卖 App 铂金展位应用 Graver 前后对比


渲染速度快


Graver 并发进行多个画板视图的渲染、显示工作。得益于图文混排技术的应用,达到了内存占用低,渲染速度快的效果。由于排版数据是不变的,所以内部会进行缓存、复用,这又进一步促进了整体渲染效率。Graver 既做到了高效渲染,又保证了低时延页面加载。



图 5 渲染效率说明


以“少”胜“繁”


Graver 重新抽象封装 CoreText、CoreGraphic 等系统基础能力,通过少量系统标准图形绘制接口即可实现复杂界面展示。


基于位图(Bitmap)的轻量事件交互系统


如上述所说,界面展示从传统的视图树转变为一张位图,而位图不能响应、区分内部具体位置的点击事件。Graver 提供了基于位图的轻量事件交互系统,可以准确识别点击位置发生在位图的哪一块“绘制单元”内。该“绘制单元”可以理解为与我们一贯使用的某个具体 UI 控件相对应的视觉展示。使用 Graver 为某一视觉展示添加事件如同使用系统 UIButton 添加事件一样简单。


全新的视觉元素分解思路


Graver 一改界面编程思路,与传统的通过控件“拼接”、“添加”,视图排列组合方式构建界面不同,它提供了灵活、便捷的接口让我们以“视觉所见”的方式构建界面。这一特点在下文 Graver 使用 中详细阐述,正是因为该特点实现了研发效率的提升。


Graver 使用

Graver 引入了全新的视觉元素分解的思路。借助该思路可以实现通过一种对象来表达任一视觉元素、甚至是任一视觉元素的组合,从而消除界面布局的复杂性。


我们先来回顾下传统界面的构建方式,以外卖 App 商家卡片其中一种样式为例,如图 6 所示:



图 6 外卖 App 商家卡片


在实现商家卡片的界面样式时,通常会根据视觉上的识别、交互要求来建立界面展示与系统提供的 UI 控件间的映射关系。以标号②位置的样式为例,在考虑复用的情况下通常这部分会使用三个系统控件来完成,分别是左侧蓝底的“预订”使用 UILabel 控件、右侧的蓝色边框“2.26.21:30 起送”使用 UILabel 控件、把左右两侧 UILabel 控件装起来的 UIView 控件;在确定好采用的 UI 控件之后,需要针对展示样式分门别类的设置各个控件的渲染属性来实现图示 UI 效果,渲染属性通常一部分预设,一部分根据业务数据的不同再进行二次设置;其次,设置各个控件的内容属性实现业务数据内容的展示,展示的内容一般是网络业务数据经逻辑处理、加工后的数据。如果涉及到点击事件,还需要添加手势或者更换成 UIButton 控件。接下来,需要根据视觉要求实现排版逻辑,以标号⑧、⑨为例,当标号⑧位置的数据没有的情况下,需要上提标号⑨位置的“美团专送”到图示标号⑧位置。诸如类似的排版逻辑随处可见。对于图示任一位置的展示内容都存在上述的循环思考、编写工作。随着界面元素的增加、变化,问题会变得更加复杂。


传统的界面构建方式其实是在 UI 控件的维度去分解视觉元素,具体是做以下四方面的编写工作:


  • 控件选择:根据展示内容、样式、交互要求确定采用哪种系统控件。

  • 布局信息:UI 控件的大小、位置,即 Frame。

  • 内容信息:UI 控件展示出来的业务数据,如标号①位置的“星巴克咖啡店”。

  • 渲染信息:UI 控件展示出来的效果,如字体、字号、透明度、边框、颜色等。


最后,将各个控件以排列组合方式合成为一棵视图树。


Graver 框架提供了以画板视图为基础,通过对更底层的 CoreText、CoreGraphic 框架封装,以更贴近“视觉所见”的角度定义了全新视觉元素分解、界面展示构建的过程。


通常“视觉所见”可划分为两部分:静态展示、动态展示。静态展示包含图片、文本;动态展示包含视频、动画等。在视觉展示全部为静态内容的时候,一个 Cell 即是一个画布,除此以外没有任何 UI 控件;否则,可以按需灵活的进行画布拆分来满足动画、视频等需要。



图 7 画板和传统视图树


以图 6 商家卡片中标号②、⑧为例,新实现方式的伪代码是这样的:


WMMutableAttributedItem *item = [[WMMutableAttributedItem alloc] init];
复制代码


[[[[item appendImage:[[UIImage wmg_imageWithColor:"blue"] wmg_drawText:"预订"]]          appendImage:[[UIImage wmg_imageWithColor:"clear" borderWidth:1 borderColor:"blue"] wmg_drawText:"2.26.21:30起送"]          appendWhiteSpaceWithWidth:"width"]//总体宽度减去②和⑧的宽度总和剩余部分         apendText:"50分钟|2.5km"];
复制代码


上述实现方式即是把标号②、⑧部分作为一个整体来实现,任何单一系统控件都无法做到这一点。


Graver 渲染原理


图 8 Graver 工作时序


如图 8 所示,Graver 涉及多个队列间的交互,以外卖 App 商家列表为例,整体流程如下:


  • 主线程构建请求参数,创建请求任务并放入网络线程队列中,发起网络请求。

  • 网络线程向后端服务发起请求,获得对应的业务模型数据(如包含了店铺名称,商家头图,评分,配送时长,客单价,优惠活动等店铺属性的商家卡片列表)。

  • 网络线程创建包含业务模型数据(如商家卡片列表)的排版任务,提交到预排版线程处理,进入预排版流程。预排版队列取出排版任务,交由布局引擎计算 UI 布局,将业务模型解析成可被渲染引擎直接处理的,包含布局、层级、渲染信息的排版模型。解析结束后,通知主线程排版完成。

  • 主线程获取排版模型后,随即触发内容显示。根据相对屏幕位置及出现的先后顺序,创建包含将需要显示区域信息的绘制任务,放入异步绘制线程队列中,发起绘制流程。

  • 异步绘制线程队列取出绘制任务,进行图文绘制,最终输出一张包含了图文内容(如商家卡片)的图片。绘制任务结束后,通知主线程队绘制完成,主线程随后展示绘制区域。


整体按照队列间串行、队列内并行的方式执行。


业务应用

Graver 在外卖内部发布之后,我们也将其推广到更多的业务线,并希望 Graver 能够成为对业务开展有重要保障的一项基础服务。经过半年多的内部试用,Graver 的可靠性、渲染性能、业务适应能力也受到外卖内部的肯定和认可。截止发稿时,Graver 已经基本覆盖了美团 App 的外卖频道、独立外卖 App 核心业务场景的大多数业务。下面列举 Graver 在外卖业务的部分应用案例:



09 业务应用


经验总结

总结一下,对于界面渲染性能优化而言,要站在一个更高角度来思考问题的解决方案。横向上,从普适性角度解决性能瓶颈点,避免其他人遇到类似问题的重复工作;纵向上,从长远考虑问题做到防微杜渐,一次优化,长期受益。基于此,我们提出一站式、标准化的渲染性能解决方案。诚然,这会遇到很多难点。面对界面样式构建的问题,系统 UIKit 框架着实为我们提供了便利,然而有时候我们需要跳出固有思维,尝试建立一套全新界面构建、视觉元素分解的思路。


参考资料


作者简介

  • 洋洋,美团高级工程师。2018 年加入美团,目前负责【美团外卖】和【美团外卖频道】的 iOS 客户端首页业务,以及支撑首页业务的技术架构、工具和系统的开发和维护工作。


2020 年 2 月 25 日 20:31398

评论

发布
暂无评论
发现更多内容

初窥Ray框架

行者AI

深度学习

「开源」首次被列入“十四五”规划,未来大有可为

百度开发者中心

终于有腾讯架构师把困扰我多年的《计算机网络原理》全部讲明白了

Java 程序员 架构 网络 计算机

2021年金三银四最新美团、字节、阿里、腾讯Java面经,已拿offer!

Java架构之路

Java 程序员 架构 面试 编程语言

mysql事务隔离的研究

这就是编程

纹理打包器TexturePacker

空城机

UI 4月日更 Texture Packer 纹理打包器 pixi

阿里最新发布Spring Cloud ALiBaBa全解第三版开源!

Java架构追梦

Java 阿里巴巴 架构 面试 SpringCloud Alibaba

中间件技术在百度云原生测试中的应用实践

百度开发者中心

中间件

飞桨框架2.0正式版重磅发布,一次端到端的“基础设施”革新

百度开发者中心

乡村振兴:AI+乡村的下一个命题

百度开发者中心

架构可视化支撑系统演进探索

华为云开发者联盟

架构 软件系统 架构可视化 辅助系统 架构可视化辅助系统

软件测试面试题【2021模拟面试整理版(含答案)】

程序员阿沐

面试 软件测试

月薪30K以上的C/C++Linux后台服务器开发学习路线是怎样的?

赖猫

c++ Linux 后台开发 后端

为什么主动跨数据复制在5G时代非常重要?

VoltDB

数据分析 5G VoltDB 电信

Impala简介以及与Hive的异同

五分钟学大数据

4月日更 impala

百度应用部署秘籍

百度开发者中心

开放原子超级链动态内核上线,十分钟可搭建一条区块链

百度开发者中心

San介绍以及在百度APP的实践

百度开发者中心

CMS垃圾收集器

张sir

Java JVM 垃圾收集

工作中的设计模式 —— 策略模式

程序员小航

Java 设计模式

Linux后台开发面试总结

赖猫

iOS 面试策略之算法基础1-3节

iOSer

ios 面试 算法 iOS算法

大牛荐书 | 百度技术大牛都在读的7本书!

百度开发者中心

学会 Java 数据结构,想不飘都难

学Java关注我

Java 编程 架构 程序人生 计算机

三年Java程序员成功跳槽涨薪,这份《阿里巴巴金三银四Java高级面试题》给了我很大的帮助。

Java架构之路

Java 程序员 架构 面试 编程语言

HugeGraph图数据库获Apache TinkerPop官方认证

百度开发者中心

「云智公开课」百度沧海·存储

「云智公开课」百度沧海·存储

美团开源Graver框架:用“雕刻”诠释iOS端UI界面的高效渲染_文化 & 方法_美团技术团队_InfoQ精选文章