当前位置:   article > 正文

探讨跨平台技术与跨平台UI框架及Kotlin Multiplatform在bilibili的实践_flutter kotlin multiplatform

flutter kotlin multiplatform

跨平台语言benchmark大横评

在这个部分,我们将对几种主要的跨平台语言进行比较,主要从执行效率、引入testcase前后app体积变化、运行内存峰值和运行内存的overhead这几个方面进行考察。

对比的平台在iOS、AndroidOS、HarmonyOS这三个平台上进行测试,由于不同平台的硬件设备无法做到一致,所以我们会在各平台选一款设备作为测试标准。

对比的语言在目前bilibili实际生产环境中使用到的语言,分别为Kotlin、JavaScript、Dart、C++、Swift。

测试方式

测试集

关于测试集,考虑到真实研发场景在研发过程中其实多数在于Model的操作,又由于bilibili大多使用grpc作为通信协议,积累了较多的真实业务场景的protobuf文件, 所以我们会使用这些proto文件作为测试集,并以最常见的序列化&反序列化作为测试用例,分别在这几种语言上进行测试。在本文中选取了当前B站的较常使用的一组protobuf, .proto个数为237个, .proto体积为2.2MB的测试集。

测试流程

1. 基于每个平台 X 每种测试语言的环境构造测试工程

  • 拥有最基本的调用testcase的UI及统计能力。

  • 防止testcase自身的依赖被strip,最基简单的对应的protobuf的序列化反序列化的调用。

部分语言的工程环境支持多平台,例如Flutter、Kotlin Multiplatform等我们会在多平台使用同一份测试工程。

2. testcase 构造

  • 基于以下protoc插件生成对应语言代码,在这我们假设各个protoc compiler尽可能以最优的方式生成代码。

语言

编译器

protoc compiler

备注

Kotlin

1.9.23

基于streem/pbandk自研

TypeScript

/

bufbuild/protobuf-es

在只可运行JS runtime的环境中通过

webpack(mode=production)进行打包

Dart

3.3.3

protocolbuffers/protobuf

C++

Apple clang version 15.0.0 (clang-1500.1.0.2.5)

protocolbuffers/protobuf

  • 我们自研了测试中的所有语言的testcase的protoc插件,通过这个插件我们可以生成每个proto文件对应的序列化反序列化的testcase,具体行为为遍历所有的Message, 并构造这个Message,后序列化成ByteArray后再反序列化回去。在各语言构造对应protobuf的序列化反序列化代码举例如下:

  1. // fission.proto 对应的 cpp 测试模块
  2. namespace bilibili_::account_::fission_::v1_::fission_::proto {
  3. template<typename Message>
  4. inline void TestMessage() {
  5. auto str = Message().SerializeAsString();
  6. auto msg = Message().ParseFromString(str);
  7. }
  8. inline void Test() {
  9. TestMessage<::bilibili::account::fission::v1::EntranceReq>();
  10. TestMessage<::bilibili::account::fission::v1::EntranceReply>();
  11. TestMessage<::bilibili::account::fission::v1::AnimateIcon>();
  12. TestMessage<::bilibili::account::fission::v1::WindowReq>();
  13. TestMessage<::bilibili::account::fission::v1::WindowReply>();
  14. TestMessage<::bilibili::account::fission::v1::PrivacyReq>();
  15. TestMessage<::bilibili::account::fission::v1::PrivacyReply>();
  16. }
  17. }
  1. // fission.proto 对应的 kotlin 测试模块
  2. @file:OptIn(ExperimentalSerializationApi::class)
  3. package bilibili_account_fission_v1_fission
  4. import kotlinx.serialization.*
  5. import kotlinx.serialization.protobuf.*
  6. import kotlinx.serialization.protobuf.ProtoBuf.*
  7. import com.bapis.bilibili.account.fission.v1.*
  8. fun doTest() {
  9. ProtoBuf.decodeFromByteArray<KEntranceReq>(ProtoBuf.encodeToByteArray(KEntranceReq()))
  10. ProtoBuf.decodeFromByteArray<KEntranceReply>(ProtoBuf.encodeToByteArray(KEntranceReply()))
  11. ProtoBuf.decodeFromByteArray<KAnimateIcon>(ProtoBuf.encodeToByteArray(KAnimateIcon()))
  12. ProtoBuf.decodeFromByteArray<KWindowReq>(ProtoBuf.encodeToByteArray(KWindowReq()))
  13. ProtoBuf.decodeFromByteArray<KWindowReply>(ProtoBuf.encodeToByteArray(KWindowReply()))
  14. ProtoBuf.decodeFromByteArray<KPrivacyReq>(ProtoBuf.encodeToByteArray(KPrivacyReq()))
  15. ProtoBuf.decodeFromByteArray<KPrivacyReply>(ProtoBuf.encodeToByteArray(KPrivacyReply()))
  16. }
  1. import Foundation
  2. import SwiftProtobuf
  3. fileprivate func testMessage<T:SwiftProtobuf.Message>(type: T.Type) {
  4. let message = T()
  5. do {
  6. let encoded = try message.serializedData()
  7. let decoded = try T(serializedData: encoded)
  8. } catch {
  9. print("Error: \(error)")
  10. }
  11. }
  12. func testBilibiliPmmsV1PmmsProto() {
  13. testMessage(type: Bilibili_Pmms_V1_GetPullMessagesReq.self)
  14. testMessage(type: Bilibili_Pmms_V1_GetPullMessagesResponse.self)
  15. testMessage(type: Bilibili_Pmms_V1_Position.self)
  16. testMessage(type: Bilibili_Pmms_V1_ControlParams.self)
  17. testMessage(type: Bilibili_Pmms_V1_Message.self)
  18. }
  • 构造TestEntry入口,收集并调用刚才生成所有的TestCase代码。

3. 编译&链接&运行

  • 在各个平台上Cpp上编译&链接参数分别为-Os -fvisibility=hidden -fvisibility-inlines-hidden -dead_strip

  • 其他语言基本使用默认的Release编译方式

  • 由于Dart runtime和Flutter engine绑定较深,所以我们直接使用flutter并使用Dart aot进行测试

  • 由于Android平台并没有原生系统自带的JsRuntime,故我们在iOS中使用的是JavaScriptCore ,在Harmony中使用的是默认的ArkRuntime

  • 由于精力有限我们并没有测试Flutter在鸿蒙的数据表现

4. 通过各个平台的Profile工具进行数据的人工收集

测试结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/959134
推荐阅读
相关标签