首页 > 其他分享 >揭秘动态化跨端框架在鸿蒙系统下的高性能解决方案

揭秘动态化跨端框架在鸿蒙系统下的高性能解决方案

时间:2024-10-08 14:11:53浏览次数:8  
标签:鸿蒙 虚拟机 JS 组件 线程 跨端 V8 动态化

作者:京东科技 胡大海

前言

动态化跨端框架(后文统称“动态化” )是一个由京东金融大前端团队全自主研发的,一份代码,可以在HarmonyOS、iOS、Android、Web四端运行的跨平台解决方案。在研发团队使用后可大幅降低研发人力成本;为业务提供实时触达、A/B触达等能力以提升业务投放效率;同时保障了C端用户优秀的用户体验。

一、动态化跨端框架原理介绍

 

 

通过上图,我们先了解一下动态化跨端框架在iOS、Android等多个平台实现跨端的原理:

① 业务层: 业务代码经过打包后形成business.js发布到云端,被Harmony、iOS、Android、H5四端共用。

② 虚拟机层: 虚拟机的核心职责是运行js代码,这也是跨平台框架的基础,在iOS使用系统内置的JSCore,在Android使用V8,在浏览器使用Webkit,在鸿蒙系统我们依然需要一个能够运行js代码的虚拟机

③ 通讯层: 在iOS和Android端使用了json数据格式进行通讯数据的传输,在鸿蒙系统也可以使用该方案。

④ 渲染层: 使用各个系统的系统组件进行UI元素的渲染。

二、基于方舟虚拟机的方案探索

1、方舟字节码概念

方舟字节码(Ark Bytecode),是由方舟编译器编译ArkTS/TS/JS生成的,提供给方舟运行时解释执行的二进制文件,字节码中的主要内容是方舟字节码指令。

2、在方舟虚拟机中运行JS

方舟虚拟机不能直接运行当前在V8中运行的js代码,但是能够执行方舟字节码,所以我们可以借助鸿蒙提供的工具将js代码转化为方舟字节码,这样就能利用鸿蒙系统的方舟虚拟机执行我们的js代码了。

 

 

3、存在的问题

3.1、业务无法热更新

在iOS和Android端,业务可以随时打包后在云端发布新的版本,借助于JSCore或者V8就可以直接运行新的版本的js,这样就支持了业务的热更新发布。但在鸿蒙系统上,华为基于安全考虑,business.abc这样的字节码文件不支持动态下发,需要内置到APP中,这样就失去了业务热更新的能力。

3.2、单线程性能问题

在其他两端我们是开启了一个单独的JS线程,进行business.js文件的执行,但是如果我们使用方舟虚拟机执行business.js转换来的business.abc的时候,其实是在方舟虚拟机的UI主线程运行了这个文件。在其他两端js文件在JS线程执行的时候,UI渲染和交互是并行不受影响的,但是在方舟虚拟机单线程下abc文件的执行和UI渲染&交互变成了串行,这样必然会严重影响页面渲染速度和交互的流畅度。

业务不能热更新以及单线程性能不佳等问题的存在,我们决定使用另一种方案-V8虚拟机。

三、基于V8虚拟机的方案落地

1、在V8虚拟机中运行JS

如果能把V8移植到鸿蒙系统中,我们就可以像其他两端一样使用多线程并且能实现业务热更新等特性,但是V8是一个近千万级代码的庞大仓库,需要掌握CMake、Clang、LLVM、Ninja等一系列交叉编译知识(嵌入式范畴),对于应用开发者是一个巨大的挑战,虽然我们已经掌握了V8移植到鸿蒙的技术,但从包大小、稳定性、兼容性、维护成本等维度看,华为厂商内置V8是一个具有长期收益的重大事项,通过和华为持续沟通,最终华为将V8内置到了操作系统,业界所有类动态化框均可直接使用内置V8虚拟机进行跨端框架的适配。

 

 

2、高性能核心方案

2.1、多线程架构

多线程是提高程序性能最直接、最有效的手段之一,借助于鸿蒙系统内置的V8虚拟机,我们就能像iOS、Android两端一样使用三线程模型完成动态化跨端框架在鸿蒙系统的渲染过程。

JS线程负责将业务代码解析为一颗虚拟Dom树、发出渲染命令、处理业务逻辑等,通过接口定义的桥方法发送给组件线程进行处理。我们以添加一个点击按钮节点为例,JS线程会通过“添加节点”这个接口以JSON描述的方式,将信息传递给组件线程,组件线程根据JSON描述将这个点击按钮节点添加到组件树中,然后触发UI线程创建系统组件,比如在鸿蒙系统会创建一个ArkTS的按钮组件,在iOS系统会创建一个UIButton组件。

UI线程负责用户页面滑动、点击事件等交互行为,当发生比如用户点击事件后,同样通过接口定义的桥方法“调用JS”,将点击事件传递给JS线程进行处理,紧接着继续处理UI线程的任务,这样UI线程的交互效率就高了,充分保障了用户良好的操作体验。


//JSON描述示例
{
    "type":"btn",
    "value":"按钮",
    "childrens":[],
    "id":"238346e885ee",
    "style":{
        "width":"66px"
    },
    "attr":{
        "text-color":"#FFFFFFFF"
    },
    "event":{
        "onclick":"myclick()"
    }
}

2.2、JSI技术引入

通讯桥存在的问题

动态化基于三个线程并行运行的方式,使其渲染性能已经接近于原生的渲染性能,但是在一些频繁通讯场景,通讯桥会“堵塞”,比如当业务需要监听一个页面的滑动而改变另外一个元素背景色的透明度,那么JS线程大部分时间在处理接收列表滑动距离,改变元素背景色透明度这个任务中,其他任务的执行会被严重影响。另外JSON数据传输的序列化和反序列化过程也会带来很大的线程性能损耗。

 

 

解决方案-JSI

之前使用通讯桥的一个主要原因就是 C++ 中的函数没办法完整映射到 JavaScript 中,让 JavaScript 直接调用,所以只能选择以序列化字符串的形式通过通讯桥传输。而JSI做的事情就是将 C++ 中的常用类型(函数、对象等)一一映射到 JavaScript 中,我们就能在JS中直接调用C++的函数和对象了。因为消除了桥通讯带来的序列化和异步调用的开销,大大提升了线程通讯性能。

 

 

四、进一步优化的方向

1、减少UI层级

当前基于多线程和JSI的架构模式在鸿蒙系统的性能还算不差,但是在鸿蒙系统上同样一个业务的UI层级是其他两端层级的约2倍。原因在于在鸿蒙系统使用系统组件进行递归渲染的时候,需要借助自定义组件进行实现,然而和iOS和Android端的命令式组件渲染不同,比如RomaDiv对应iOS就是直接翻译为UIView即可,在鸿蒙必须增加一个包裹的容器才是一个合法的自定义组件,比如Stack容器,这样每个组件的层级就多了一层,层级过多会直接影响渲染性能,在一些复杂业务场景到达一定层级后会造成页面掉帧和卡顿。


@Componentexport 
struct RomaDiv 
{ 
    build()
    { 
        Stack(){
         //借助wrapBuilder实现递归 
         ForEach(this.childrenTags, (childrenTag) => 
             { 
                 RomaComponentFactory.builder()//RomaComponentFactory就是对应鸿蒙系统提供的WrappedBuilder 
             }) 
         } 
    } 
}

面对业界跨端框架面临的这个共性问题,鸿蒙系统提供了C语言的命令式接口进行组件创建,C组件接口是介于UI组件的Native实现和ArkTS对接层之间的一层C接口封装,它绕过了状态管理对组件变化、刷新的自动化管理,因此具有较好的性能。同时经过初步验证,接入C-API后,UI层级能直接和另外两端保持一致,同时渲染性能也会得到大幅提升。

2、降低通讯成本

当前JSI在鸿蒙系统的应用中通过JSI打通C++,再通过NAPI从C++打通ArkTS,跨语言通讯成本高。如果接入了C-API,就避免了C++和ArkTS之间类型互相转换和跨语言调用的开销,也能带来不少的性能提升。

 

3、JS逻辑下沉到C++

在当前架构中,JS线程运行着V-Dom树创建、对比,样式&属性解析等一系列繁重的框架逻辑,如果我们能将这些JS代码逻辑下沉到C++,框架逻辑运行效率会进一步提升。

 

总结

本文讲述了如何在鸿蒙系统中实现“动态化”跨端框架的高性能运行。包含探索方舟虚拟机运行方案时遇到的问题,以及基于V8虚拟机方案的具体提升手段和后续进一步提升的方案。通过阅读,你将能够更好地理解和应用这些技术,提高跨端框架的性能,提升C端用户体验。

标签:鸿蒙,虚拟机,JS,组件,线程,跨端,V8,动态化
From: https://www.cnblogs.com/Jcloud/p/18451524

相关文章

  • 鸿蒙 Next 实战: 电子木鱼
    前言正所谓:HelloWord是程序员学任何一门语言的第一个程序实践。这其实也是一个不错的正反馈,那如何让学习鸿蒙Next更有成就感呢?下面就演示一下从零开发一个鸿蒙Next版的电子木鱼,主打就是一个抽象! 实现要点页面布局木鱼点击木鱼音效动画特效自定义弹窗 开始实......
  • 鸿蒙 Next 实战: 环境搭建
    前言作为独立开发者,如果我们错过了传统移动App,和后起小程序的红利,那万物互联+AI的应用开发就得抓住了。虽然个人上架应用平台难易都差不多,但是鸿蒙生态当前正需要广大开发者参与,一旦上架,相比其他平台,流量扶持力度更大,变现能力也更容易。所以,我们可以先开发一些应用占个位置......
  • 关于鸿蒙自己搭建项目环境要注意的点
    具体步骤如下https://xie.infoq.cn/article/4c72d00fab3499bc78de4fdd3但是与nativec++相关的东西不止上面还少不了CMakeList.txt, #theminimumversionofCMake.cmake_minimum_required(VERSION3.5.0)project(MyApplication)set(NATIVERENDER_ROOT_PATH${CMAKE_CU......
  • 鸿蒙应用示例:镂空效果实现教程
    在鸿蒙系统中,为了给用户带来更加生动的视觉体验,我们可以使用不同的技术手段来实现图像和文字的镂空效果。本文将通过三个具体的示例来展示如何在鸿蒙系统中实现实心矩形镂空、实心圆镂空以及文字镂空的效果。示例代码//定义一个名为Index的应用入口组件@Entry@Componentstruct......
  • 鸿蒙应用示例:实现文本高亮与自动换行
    在设计应用界面时,我们常常需要对某些重要的文本进行高亮显示,以引起用户的注意。同时,在一些场景中,我们需要确保长文本能够自动换行,以适应不同的屏幕尺寸和布局需求。本文将通过两个示例,分别展示如何在HarmonyOS应用中实现这些功能。【示例一】文本高亮显示@Entry@Componentstruct......
  • 鸿蒙应用示例:ArkTS中设置颜色透明度与颜色渐变方案探讨
    /***根据比例混合两个十六进制颜色值。*@paramcolorA第一个颜色的十六进制值,例如红色'#ff0000'。*@paramcolorB第二个颜色的十六进制值,例如黑色'#000000'。*@paramratio混合比例,0表示仅返回colorA,1表示仅返回colorB,介于0和1之间的值会混合两个颜色。......
  • 鸿蒙应用示例:应用开发中的动态获取属性与调用方法技巧
    随着HarmonyOS的发展,API版本的更新带来了许多新的特性和限制。在API11及以后的版本中,直接赋值对象的语法不再被支持,这要求开发者们采用新的方式来处理对象的创建和属性的访问。同时,HarmonyOS支持ETS(EnhancedTypeScript)文件,这是一种扩展了TypeScript的文件格式,用于更好地支持Harmo......
  • 鸿蒙应用示例:NEXT 中 Map 类型的使用及注意事项
    在JavaScript中,Map对象允许存储任何类型的键和值,提供了键值对的存储功能。在HarmonyOS中,Map的使用基本遵循JavaScript的标准,尤其是要注意set赋值只能用get获取,而索引赋值只能用索引获取。且它们可以同时赋值但遍历的方式又不同。【Map对象的赋值与获取】使用set方法赋值当你需要......
  • 鸿蒙应用示例:键盘管理从避免遮挡到显示监听的方案实践
    在HarmonyOS应用开发中,键盘管理是一个关键环节,直接影响着用户体验。本文将探讨HarmonyOS键盘管理的几个重要方面,包括如何避免软键盘遮挡输入框、键盘显示与隐藏的监听机制,以及如何手动控制键盘的显示与隐藏。一、避免软键盘遮挡输入框在默认情况下,当用户在输入框中输入文本时,软键盘......
  • 鸿蒙智联仅此4家生态解决方案合作伙伴
    在当今快速发展的物联网时代,鸿蒙智联(HarmonyOSConnect)作为华为面向智能硬件生态伙伴打造的全新品牌和开放平台,正引领着智能硬件行业的变革与创新。鸿蒙智联生态解决方案合作伙伴,作为这一生态中的重要力量,通过提供全方位的解决方案和技术支持,助力生态产品伙伴快速融入鸿蒙智联......