5分钟带你看懂 GCanvas渲染引擎的演进(二)

2019 年 12 月 17 日

5分钟带你看懂 GCanvas渲染引擎的演进(二)

架构演进与优化

以业务先赢的基本原则,保证业务的前提下,架构容器和升级变化过程中,GCanvas 引擎也经历了演进和升级优化。

2017 年的架构
以插件为主的实现,仅支持移动端

最新架构
提供标准接口,链路升级,API 升级,不仅支持移动端还支持服务端


架构变化主要有以下几个方面:

  • 适配支持更多的 JS 框架和库
  • JS 到 Native 调用通路,从模块路由反射升级到 JSBinding
  • 渲染 API 支持 Metal
  • 增加 MacOS 和 Linux 平台支持

► 内功修炼

在快速迭代过重中,保持修炼内功。为保证高性能这个根本,在链路、内核以及底层图形 API 等方面也都做了不少优化与升级。

JS 到 Native 链路优化

从 Weex 调用链路到 JSBinding,Weex 容器的 JS 到 Native 的通路采用模块路由和反射的调用方式调用具体的模块和组件。在 UI 和一些非高频的场景完全能满足需求。

但是对于连续操作、连续动画等高频的 JS 到 Native 通讯的场景,链路上的耗时非常大,导致卡顿产生。这也是为什会 BindingX 和 GCanvas 的 JSBinding 的出现。

BindingX 是另一种解决频发通讯消耗的方案,有兴趣的可以看下 BindingX。(地址戳阅读原文)

GCanvas 的 JSBinding 的实现:通过链路调用的改造,整体帧率平均提升 10 帧左右。Android 和 iOS 的 JSBinding 实现方案类似。

以 iOS 举例说明:iOS 尝试使用 JSExport 和全局方法,两种 JSBinding 方案。

  • 第一种方案,使用 JSExport 和 JSExportAS
复制代码
@import JavaScriptCore;
@protocol TestObjecJSExport <JSExport>
JSExportAs(foo, - (void)foo:(NSString *)msg);
@end

第二种方案,使用 C Export 将方法和属性用 JSStaticFunction 和 JSStaticValue 进行绑定

复制代码
// 方法 JSStaticFunction
typedef struct {
const char* name; // 方法名
JSObjectCallAsFunctionCallback callAsFunction; //Native 方法实现
JSPropertyAttributes attributes; // 方法设置
} JSStaticFunction;
// 属性 JSStaticValue
typedef struct {
const char* name; // 属性名
JSObjectGetPropertyCallback getProperty; //Native 属性 Getter 实现
JSObjectSetPropertyCallback setProperty; //Native 属性 Setter 实现
JSPropertyAttributes attributes; // 属性的读写设置
} JSStaticValue;

两种实现方案,经过测试对比第二种方案在性能更好。原因在于静态 JS 方法是通过方法名到 Native 函数的直接映射,而 JSExport 的方案则需要类型检查,协议校验,再调用 Native 方法中间经过额外的处理。

简单的耗时测试数据对比:

JS 到 Native 数据传输
方法调用与属性访问之外,参数数据的传输也影响每帧耗时,尤其是在 WebGL 的场景,通常有很大顶 点数据需要处理,有几万 - 几十万字节,甚至更多。JS 到 Native 的大数据传输避免内存拷贝。

JS 与 Native 对象生命周期
JSBinding 的对象生命周期管理,JS 对象与 Native 对象一一对应,在 JS 对象创建触发 JSObjectInitializeCallback 回调,创建 Native 对象,并将 JS 与 Native 建立关联。JS 的 GC 回收对象触发 JSObjectFinalizeCallback 的回调中去释放对应 Native 对象。

帧率优化
除了调用链路对帧率的提升,单帧绘制的 CPU 和 GPU 耗时相关的优化点

  • 顶点数据计算,顶点数据合并提交
  • 优化缓存策略,优化文字相关纹理的缓存
  • 增加状态管理,减少 GPU 提交数据和频次
  • 优化多边形填充效率
  • 抗锯齿等耗时特性可选

w3c 标准完善

  • 支持阴影
  • 支持虚线
  • 支持多 Clip 区域嵌套
  • 支持 Winding Rule 支持

扩展能力,扩展一些非标接口支持 Sketch 渲染,

  • 阴影的扩散
  • 路径的图案填充
  • 路径的高斯模糊
  • 路径的内描边和外描边

底层图形 API 升级
在 iOS12 之后,苹果将 OpenGL ES API 设为废弃,在已支持的设备上 OpenGL ES 的调用都已映射到 Metal 相应的后端实现,Metal 替换 OpenGL 势在必行。GCanvas 也已投入开发 Metal,可选择使用 Metal 作为渲染的后端。已完成了 2D 的绝大部分能力。

选择 Metal 会带来以下方面的收益:

  • 内存数据使用更高效,内存数据可共享,
  • 尽可能的榨取更多 GPU 性能
  • 摆脱 OpenGL 的状态机,更友好的面向对象编程
  • 苹果后续的持续投入和更新
  • 丰富的调试工具,能精确到每个顶点数据和每个素点颜色
  • 便捷调试这着色器语言 (Metal Shader Language)

在内核升级优化的过程中,也有很多同学积极参与其中来在此表示感谢。

稳定性

增加了 API 的自动化测试以及 CI 建立保障稳定性。

未来的方向

GCanvas 开源社区加大投入增加社区影响力, 请大家积极关注并 star
更多纹理压缩格式的支持
Vulkan 的持续演进
更多平台的支持,IoT 设备上应用
与云端渲染的融合,提供 Fass 能力
WebGPU 以及 GPU 计算方向探索
WebAssembly 的应用

本文转载自淘系技术公众号。

原文链接: https://mp.weixin.qq.com/s/8NafSk2Yfl1eCEDNBeYy1g

2019 年 12 月 17 日 14:11 47

评论

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

架构师训练营作业一:食堂就餐卡系统设计

常江舟

极客大学架构师训练营

食堂就餐卡设计说明书

02-kubernetes自建CA及双向TLS认证

绿星雪碧

Kubernetes TLS CA证书

LocalDateTime和Date的比较与区别

彭阿三

时间格式化 LocalDateTime Date

系统/子系统/模块/组件/框架/架构

gen_jin

【第一周作业】食堂就餐卡系统设计

黑莓

架构方法:架构师如何做架构

数据库周刊27丨6月最新国产数据库排行;OB成立新公司奥星贝斯;腾讯云发布图数据库TGDB;Oracle坏块修复;MySQL故障排查导图;经典SQL语句大全...

墨天轮

数据库

Android 无埋点从入门到放弃:了解 Java 字节码

GrowingIO技术专栏

架构师训练营--第1周总结感想

芥菜

玄姐公开课总结【构建基于ServiceMesh的普适业务中台架构】

魔曦

架构 Service Mesh

你并不理解i++和++i

flyhero

Java 程序员 JVM i++

钟离昧的一梭子架构师之旅

X中倪

架构师训练营第一周学习总结

0x12FD16B

清华大佬马士兵告诉你阿里巴巴P5到P8级需要掌握哪些技术?

周老师

Java 程序员 架构 微服务 马士兵

架构师课程学习第一周心得

秤须苑

极客大学架构师训练营

让独立思考成为习惯

Neco.W

深度思考 学习方法 思考

架构第一课学习总结

师哥

游戏夜读 | 如何成长为游戏人?

game1night

Intellij IDEA 右击没有run

程李文华

钟离昧的第一张架构设计图之旅

X中倪

Week 01 食堂饭卡系统设计

Geek_165f3d

架构师训练营第一周学习总结

常江舟

极客大学架构师训练营

量子技术到底有哪些突破值得重点关注?

蔡芳芳

30岁,就被大厂抛弃了

Jeff.Smile

求职

架构师训练营-Week1-作业1

车小勺的男神

小师妹学JavaIO之:NIO中Channel的妙用

程序那些事

io nio 小师妹 buffer channel

SpringBoot分布式任务中间件开发 附视频讲解 (手把手教你开发和使用中间件)

小傅哥

小傅哥 中间件 springboot 分布式任务

使用VSCode连接到IBM Cloud区块链网络

程序那些事

智能合约 hyperledger fabric ibm cloud

【第一周】学习总结

黑莓

架构师训练营-Week1-作业2

车小勺的男神

5分钟带你看懂 GCanvas渲染引擎的演进(二)-InfoQ