1# 合理使用IPC通信 2 3# **背景** 4 5应用使用操作系统提供的IPC(Inter-Process Communication,进程间通信)机制进行跨进程通信是通用场景, 当前系统基于Binder驱动封装了一套IPC机制,提供了应用和系统服务间的跨进程通信能力。 6 7IPC机制方便了进程之间的交互和通信,但是,不合理的使用IPC通信会对应用性能造成影响。 8 9在应用主线程中进行IPC通信,消息的发送和接收需要等待对方进程的响应,这会对应用主线程造成阻塞。如果操作耗时较长或者频率较高,产生的时延会引起页面卡顿、丢帧。 10 11进行IPC通信时需要进程上下文切换,从一个进程或线程切换到另一个进程或线程,会造成CPU时间片的浪费,从而降低应用性能。 12 13为了保持数据的一致性和正确性,需要使用进程同步和互斥机制,在进程之间进行协调。每个进程在对资源操作前都尝试加锁,操作结束解锁,产生了锁的获取和释放等额外开销。 14 15所以,在一些对性能要求高的场景:多人在线游戏、视频编辑、实时通信和视频等,IPC通信是一个重要优化点。 16 17# **优化思路** 18 19在应用开发过程中,合理使用IPC通信是确保应用性能和用户体验的关键因素。然而,不合理的IPC通信可能会导致性能问题。因此,可以从以下几个方面进行优化。 20 21**本地缓存数据**:合理使用本地缓存,将常用的数据存储在本地,而不是每次都通过IPC请求。这可以减少不必要的通信次数。确保缓存数据的有效期和更新策略是合理的,以防止缓存数据过期或不一致。 22 23**批处理请求**:将多个IPC请求合并成一个批处理请求,从而减少通信的次数。这对于频繁的小数据请求尤其有用。例如,在获取多个设置项时,可以一次性请求所有设置项而不是分别请求每个设置项。 24 25**异步处理**:对于不需要立即响应的IPC请求,可以将它们设置为异步处理,以免阻塞主线程。例如,后台数据同步可以在后台线程中进行,而不会影响用户界面的响应。 26 27**减少不必要的数据传输**:确保只传输应用所需的数据,避免传输不必要的信息。 28 29### 场景示例 1 30 31当前应用程序模块需要进行耗时计算,由应用程序进程和执行计算任务进程间进行IPC通信。 32 33**问题**:前台发送计算任务请求后,一直处于获取计算结果状态,界面卡死无法进行其他操作。 34 35**分析**:通过耗时分析工具`Time Profiler`观察到,在页面跳转过程中,`ArkTS Callstack`泳道存在大量的函数调用栈,总耗时达3.4s,阻塞了UI绘制渲染。 36 37 38 39**提出方案** 40 41**1**.可以先读取应用中的缓存数据,如果已经存在相同任务的计算结果,那么就不依赖于IPC通信进行获取数据。 42 43**2**.单次大数据耗时IPC通信,改为多次小数据异步IPC通信。 44 45**方案实施**: 46 47通过读取缓存目录下的缓存数据,进行数据对比 48 49```javascript 50// 获取缓存数据 51getCacheData(key: string) { 52 try { 53 let context = getContext(this) as common.UIAbilityContext; 54 let cacheFilePath = context.cacheDir + '/ComputeResult.txt'; // 应用沙箱缓存目录 55 let computeResult = JSON.parse(fs.readTextSync(cacheFilePath)); 56 // 是否存在已有耗时任务 57 if (computeResult[key] === undefined) { 58 return undefined 59 } 60 return computeResult[key] 61 } catch (e) { 62 console.error('getCacheData failed' + JSON.parse(e)); 63 } 64} 65``` 66 67通过获取到缓存数据结果,决定是否发送IPC通信请求 68 69```javascript 70if (this.getCacheData(this.taskId)) { 71 // 获取缓存数据 72 this.result = this.getCacheData(this.taskId); 73} else { 74 // 写入数据 75 data.writeStringArray(sendData); 76 // 发送IPC通信请求 77 await ReceivedData.sendMessageRequest(REQUEST_CODE, data, reply, option); 78} 79``` 80 81大数据IPC通信改为小数据批量IPC通信 82 83```javascript 84if (this.getCacheData(this.taskId)) { 85 this.result = this.getCacheData(this.taskId); 86} else { 87 let chunkSize = 10; 88 for (let i = 0;i < sendData.length; i += chunkSize) { 89 let chunk = sendData.slice(i, i + chunkSize); 90 // 写入数据 91 data.writeStringArray(chunk); 92 await ReceivedData.sendMessageRequest(REQUEST_CODE, data, reply, option); 93 } 94} 95``` 96 97 98 99**运行效果**: 100 101应用读取缓存后,运行时效果如下泳道图所示: 102 103 104 105在`ArkTS Callstack`泳道中,可以看出当前的进程中没有大量的`computed`耗时任务,而是直接调用`getCacheData`获取缓存数据,减少了应用IPC通信次数。 106 107 108 109拆分大数据后,运行时效果如下泳道图所示: 110 111  112 113在`ArkTS Callstack`泳道中,当前应用进程的`computed`耗时任务由3.4s变为227ms,性能优化明显。 114 115### 场景示例 2 116 117**问题**应用包含Page: A和Page B两个页面,Page B的主体视图是Tabs组件,Tabs组件内包含首页、WiFi列表页等数个页签,默认展示首页页签。从Page A跳转到Page B时,页面加载时间较长。 118 119**分析**:通过耗时分析工具Time Profiler对页面跳转过程进行录制并分析,观察ArkTS Callstack泳道发现该过程频繁调用`getScanInfoList`方法,产生阻塞。 120 121 122 123**提出方案**:通过查阅接口文档,`getScanInfoList`功能为获取当前扫描到的热点列表,是同步接口,会阻塞主线程。考虑到Page B的首页页签并不展示热点列表,只有在用户切换到WiFi页签时才需要展示,该扫描操作在页面跳转过程中是不必要的。因此,将该功能放在切换WiFi列表页签的处理逻辑中。 124 125**方案实施**: 126 127将Page B中`aboutToAppear`生命周期函数中获取热点列表的方法`ipcTask`移除。在Page B的Tabs组件WiFi页签中自定义组件WiFiItem,用于展示WiFi列表,将该`ipcTask`移动到WiFiItem组件的`aboutToAppear`生命周期函数中。 128 129```javascript 130aboutToAppear() { 131 this.ipcTask(); 132} 133 134ipcTask() { 135 let count = 0; 136 while (count < 100) { 137 let data = wifiManager.getScanInfoList(); 138 count++; 139 } 140} 141``` 142 143 144 145 146 147调整位置后,Page A到Page B的跳转过程耗时明显缩短,提升了用户体验。 148 149# **总结** 150 151合理使用IPC通信对于优化应用程序性能至关重要。通过场景分析、逻辑优化和合理的权衡,可以确保IPC通信不成为应用性能的瓶颈,从而提供更出色的用户体验。 152 153# **参考资料** 154 155· [1] [@ohos.rpc (RPC通信) (openharmony.cn)](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/reference/apis/js-apis-rpc.md/) 156 157· [2] [IPC与RPC通信概述 (openharmony.cn)](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/connectivity/ipc-rpc-overview.md/) 158 159· [3] [性能分析工具CPU Profiler (openharmony.cn)](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/performance/application-performance-analysis.md/) 160 161· [4] [@ohos.wifiManager (WLAN)(推荐) (openharmony.cn)](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/reference/apis/js-apis-wifiManager.md/)