HarmonyOS 鸿蒙Next ArkTs线程API threadpool和worker均基于Actor模型实现,如何解决多线程通信时消息实时性问题

发布于 1周前 作者 zlyuanteng 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next ArkTs线程API threadpool和worker均基于Actor模型实现,如何解决多线程通信时消息实时性问题

我们的业务场景中,有一类任务属于计算密集型任务,因此我们需要发起一个线程,不断地将各类数据送入线程,线程中将依赖各类数据的时间戳,对数据进行时序上的对齐,之后对齐后的数据会参与一次计算,计算频率为10~30HZ,计算结果将用于动画渲染。因此这个线程的输入数据和输出数据之间存在实时性要求,输出数据与输入数据时间差不应超过30ms,否则动画渲染将会有一定的延迟。

我们的业务场景可以描述为下图:

我们已经尝试使用鸿蒙Next提供的线程API threadpool和worker分别实现,分别遇到不同的问题

  • 使用threadpool实现,线程计算时长存在限制,计算超过3分钟,线程被系统主动终止,无法满足长时间运行需求

  • 使用worker实现,worker只有单个消息队列,多条数据流通过postMessage发送到worker时,出现消息积压,消息从发送到接收延迟长达数秒,消息的实时性丧失导致无法使用

  • 延迟统计方法如下:

宿主线程创建ARMessage时,记录系统时间戳,消息创建后立即发送

Worker线程收到消息时,计算系统时间差

// 发送消息,记录系统时间差
    public UpdateAdasPerceptionCogTree(cogTree: AdasPerceptionCogTree): void {
        if (!cogTree || !cogTree.roads) {
            return
        }
        let msg = new AdsCogTreeMsg(cogTree)
        this.arWorker.postMessage(msg)
    }

// worker内接收消息后,立即打印与创建时的时间戳差值 function processUpdateAdasPerceptionCogTreeMsg(msg: ArMessage) { let cogTree = (msg as AdsCogTreeMsg).value hilog.debug(0, “AdsCogDelay”, “,” + (systemDateTime.getUptime(systemDateTime.TimeType.STARTUP) - msg.sysTs)) } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

日志打印结果如下,延迟逐渐增加至6~7秒

10-11 10:25:38.115   AdsCogDelay  D   ,0
10-11 10:25:38.753   AdsCogDelay  D   ,21
10-11 10:25:39.317   AdsCogDelay  D   ,0
10-11 10:25:39.960   AdsCogDelay  D   ,57
10-11 10:25:40.547   AdsCogDelay  D   ,2
10-11 10:25:41.115   AdsCogDelay  D   ,20
10-11 10:25:41.776   AdsCogDelay  D   ,165
10-11 10:25:42.438   AdsCogDelay  D   ,243
10-11 10:25:42.888   AdsCogDelay  D   ,59
10-11 10:25:51.347   AdsCogDelay  D   ,7627
10-11 10:25:51.871   AdsCogDelay  D   ,7251
10-11 10:25:52.404   AdsCogDelay  D   ,7022
10-11 10:25:52.924   AdsCogDelay  D   ,6891
10-11 10:25:53.444   AdsCogDelay  D   ,6684
10-11 10:25:53.927   AdsCogDelay  D   ,6461
10-11 10:25:54.383   AdsCogDelay  D   ,6339
10-11 10:25:54.902   AdsCogDelay  D   ,6141
10-11 10:25:55.316   AdsCogDelay  D   ,5755
10-11 10:25:55.824   AdsCogDelay  D   ,5577
10-11 10:25:56.294   AdsCogDelay  D   ,5217
10-11 10:25:56.731   AdsCogDelay  D   ,4892
10-11 10:25:57.226   AdsCogDelay  D   ,4890
10-11 10:25:57.668   AdsCogDelay  D   ,4722
10-11 10:25:58.157   AdsCogDelay  D   ,4544
10-11 10:25:58.558   AdsCogDelay  D   ,4279
10-11 10:25:59.067   AdsCogDelay  D   ,3887
10-11 10:25:59.560   AdsCogDelay  D   ,3608
10-11 10:26:00.035   AdsCogDelay  D   ,3381
 

我们尝试过使用API 12,将消息封装成Sendable class,并使用ThreadWorker.postMessageWithSharedSendable()接口发送消息。按照文档的说法,Sendable class对象发送时不会发生序列化,而会发生引用的所有权转移。但事实是,消息的延迟并没有改善

之前在Android平台,我们基于共享内存的方式实现两个线程之间的消息通信,HarmonyNext似乎没有在ArkTs中提供共享内存的线程API

2 回复
基于Actor模型与共享内存模型的差异在于,共享内存会由于消息消费不及时而被覆盖,从而达到丢弃的目的;而Actor模型基于消息队列的机制保证每一条消息都得到处理

题目中出现消息阻塞的主要原因是CogTree消息较长,消息处理逻辑耗时过长,每帧耗时500ms左右,worker内只能以2HZ响应,而发送端以3HZ发送,导致消息积压

综上,应保证消费端处理消息的速度>=生产速度,才能避免消息阻塞带来的延迟

HarmonyOS 鸿蒙Next ArkTs线程API中的threadpool和worker均基于Actor模型实现,这一设计旨在提高多线程任务的执行效率和系统的整体性能。针对多线程通信时消息实时性问题,可以采取以下措施来解决:

  1. 优化线程池配置:根据任务的特性和执行时间,合理配置线程池的大小和线程优先级,确保任务能够及时得到处理。
  2. 使用高效通信机制:采用共享内存、消息队列等高效通信机制,减少线程间的通信延迟。
  3. 避免资源竞争:合理设计数据结构,避免多线程同时访问同一资源导致的竞争和锁等待问题。
  4. 监控和调优:通过监控线程池的运行状态和任务执行情况,及时发现并解决潜在的性能瓶颈。

此外,开发者还可以利用HarmonyOS提供的性能调优工具和文档,对多线程应用进行更深入的分析和优化。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部